0
\$\begingroup\$

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.

asked Oct 15, 2018 at 14:03
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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],
 }
})

answered Oct 23, 2018 at 19:32
\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Review! Your answer looks good, enjoy your stay! \$\endgroup\$ Commented Oct 23, 2018 at 22:13

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.