Home > Software engineering >  How to merge a nested array of objects in javascript with a specific shape
How to merge a nested array of objects in javascript with a specific shape

Time:05-17

I am trying to merge an array of objects by summing up the totals of each key-value pair under the totals object. For example, the below array would yield one object with a totals object of 3 apples and 5 oranges. This should be dynamic. If pears were to be a key in another object, the resulting object would include three keys under the totals object: apples, oranges, and pears.

Sample Input:

[
  {
    summary: {
      totals: {
        apples: 2,
        oranges: 3
      }
    }
  },
  {
    summary: {
      totals: {
        apples: 1,
        oranges: 2
      }
    }
  }
]

Expected Output:

{
  summary:{
    totals:{
      apples:3,
      oranges:5
    }
  }
}

What I've tried:

function mergeObjects(arr) {
  let shape = {
    summary:{
      totals:{}
    }
  }
  
  return arr.reduce((prev, cur) => {
   if(cur.summary.totals.apples){
     shape.summary.totals.apples.push(cur.summary.totals.apples)
   }
  }, shape);
}

CodePudding user response:

  • Using Array#reduce, iterate over the array while updating an object
  • In every iteration, using Object#entries and , iterate over the current totals pairs and update the accumulator.

const arr = [
  { summary: { totals: { apples: 2, oranges: 3 } } },
  { summary: { totals: { apples: 1, oranges: 2 } } },
];

const res = arr.reduce((map, current) => {
  const { totals: currentTotals = {} } = current.summary ?? {};
  const { totals } = map.summary;
  Object.entries(currentTotals).forEach(([ key, value ]) => {
    totals[key] = (totals[key] ?? 0)   value;
  });
  return map;
}, { summary: { totals: {} } });

console.log(res);

CodePudding user response:

You can try something like. Just loop through the array and sum up apples and oranges.

const arr = [
  {
    summary: {
      totals: {
        apples: 2,
        oranges: 3,
      },
    },
  },
  {
    summary: {
      totals: {
        apples: 1,
        oranges: 2,
      },
    },
  },
];

function mergeObjects(arr) {
  let shape = {
    summary:{
      totals:{
      apples:0,
      oranges:0
      }
    }
  }
  
  arr.forEach(x => {
   if(x.summary.totals.apples){
     shape.summary.totals.apples  = x.summary.totals.apples;
     shape.summary.totals.oranges  = x.summary.totals.oranges;
   }
  });
  return shape;
}

let result = mergeObjects(arr);
console.log(result);

CodePudding user response:

The second option of the reduce function initializes the value.

And the initialized value can be used in prev!

[1] store the value in prev.

[2] prev can accumulate values. You have to return to use the accumulated value. If not returned, the value will be undefined.

[3] apples is not an array type, so you cannot use the push method. it is a number type, you must use a numeric operator.

function mergeObjects(arr) {
  const shape = {
    summary: {
      totals: {},
    },
  };

  return arr.reduce((prev, cur) => {
    const { apples, oranges } = cur.summary.totals;
    // [1]
    prev.summary.totals.apples
      // [3]
      ? (prev.summary.totals.apples  = apples)
      : (prev.summary.totals.apples = apples);
    prev.summary.totals.oranges
      ? (prev.summary.totals.oranges  = oranges)
      : (prev.summary.totals.oranges = oranges);
    // [2]
    return prev;
  }, shape);
}

tips!

  1. Use Destructuring Assignment
const { apples, oranges } = cur.summary.totals;
  1. Use Ternary Operator
prev.summary.totals.apples
      ? (prev.summary.totals.apples  = apples)
      : (prev.summary.totals.apples = apples);
  • Make code look nice!

CodePudding user response:

You can combine Object.entries() with Array#reduce() and Array.forEach()

Code:

const data = [{summary: {totals: {apples: 2,oranges: 3}}},{summary: {totals: {apples: 1,oranges: 2}}}]

const result = data.reduce((a, c) => (
  Object
    .entries(c.summary.totals)
    .forEach(([k, v]) => a.summary.totals[k]  = v), a
),
{ summary: { totals: { apples: 0, oranges: 0 } } })

console.log(result)

  • Related