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.

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

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

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.