I am formatting a data result from the array of objects that looks like this:
const data = {
periods: [{
month: 'January',
sickLeave: {
differance: '-12000',
revision: '6000',
paid: '18000',
},
holidayLeave: {
differance: '10000',
revision: '22000',
paid: '12000',
},
received: '-2000',
taken: '2000',
result: '0',
},
{
month: 'Februar',
sickLeave: {
differance: '-8000',
revision: '6000',
paid: '18000',
},
holidayLeave: {
differance: '10000',
revision: '22000',
paid: '12000',
},
received: '-2000',
taken: '2000',
result: '0',
}],
};
What I want to do with this is to make a new array that looks like this:
[{
name: "sickLeaveDifferance",
result: ["-12000", "-8000"]
},
{
name: "sickLeaveRevision",
result: ["6000", "6000"]
},
{
name: "sickLeavePaid",
result: ["18000", "18000"]
},
{
name: "holidayLeaveDifferance",
result: ["10000", "10000"]
},
{
name: "holidayLeaveRevision",
result: ["22000", "22000"]
},
{
name: "holidayLeavePaid",
result: ["12000", "12000"]
},
{
name: "received",
result: ["-2000", "-2000"]
},
{
name: "taken",
result: ["2000", "2000"]
},
{
name: "result",
result: ["0", "0"]
}]
I am achieving this with this function:
const formattedResult = perioder => {
let resultArray = [];
const pushNewValue = (key, value) => {
const objectExists = resultArray.find(e => e.name === key);
if (objectExists) {
objectExists.result.push(value)
} else {
resultArray.push({
name: key,
result: [value]
})
}
};
perioder.map(el =>
Object.entries(el).forEach(([key, value]) => {
if (key != 'month') {
if (key === 'sickLeave' || key === 'holidayLeave') {
const prop = key;
Object.entries(value).forEach(([key, value]) => {
const name = `${prop + key[0].toUpperCase() + key.slice(1)}`;
pushNewValue(name, value);
})
} else {
pushNewValue(key, value);
}
}
}))
return resultArray;
}
But, I feel like there is a better, more elegant way of achieving this, just not sure how to do this?
Here is the fiddle.
1 Answer 1
Do you really anticipate the data model changing so much that this needs to be ultra flexible? In order to do so the code is quite complex - for instance having a forEach inside of an if inside of a forEach inside of a map. You already have model specific checks in the code anyways, such as the check for the 'sickLeave' and 'holidayLeave' keys. I think a solution along these lines would be perfectly acceptable:
const initialNormalizedVals = {
"sickLeaveDifferance": [],
"sickLeaveRevision": [],
"sickLeavePaid": [],
"holidayLeaveDifferance": [],
"holidayLeaveRevision": [],
"holidayLeavePaid": [],
"received": [],
"taken": [],
"result": [],
}
const normalizedData = data.periods.reduce((outcome, { sickLeave, holidayLeave, received, taken, result }) => {
outcome.sickLeaveDifferance.push(sickLeave.differance)
outcome.sickLeaveRevision.push(sickLeave.revision)
outcome.sickLeavePaid.push(sickLeave.paid)
outcome.holidayLeaveDifferance.push(holidayLeave.differance)
outcome.holidayLeaveRevision.push(holidayLeave.revision)
outcome.holidayLeavePaid.push(holidayLeave.paid)
outcome.result.push(result)
outcome.taken.push(taken)
outcome.received.push(received)
return outcome
}, initialNormalizedVals)
const transformedData = Object.keys(normalizedData).map(key => {
return {
name: key,
result: normalizedData[key],
}
})
-
\$\begingroup\$ Welcome to Code Review! Your answer looks good, enjoy your stay! \$\endgroup\$ferada– ferada2018年10月23日 22:13:42 +00:00Commented Oct 23, 2018 at 22:13