Home > OS >  Use reduce method to sum up values in array of objects and find duplicates - JS
Use reduce method to sum up values in array of objects and find duplicates - JS

Time:10-06

I have an array of objects:

const fruits = [{
    type: oranges,
    amount: 10
  },
  {
    type: apples,
    amount: 0,
  }, {
    type: oranges,
    amount: 5
  }
]

I need to do the following:

  • sum up the fruits, if they're the same (f.ex. sum up oranges: {type: oranges, amount: 15})
  • add a new key-value pair to object, depending on how many times it is present in the array (f.ex. oranges are present two times: {types: oranges, amount: 15, count: 2} and apples are present one time {types: apples, amount: 0, count: 1} )

So my goal is to have something like this:

const fruits = [{
    type: oranges,
    amount: 15,
    count: 2
  },
  {
    type: apples,
    amount: 0,
    count: 1
  }
]

I found out that the reduce method is a good way to achieve this. I'm working with the following code (this should sum up the amount), but no matter what I try I don't get the result. I just get a new key-value {..., marks: NaN} - so maybe there's a better approach:

const fruits = [{
    type: "oranges",
    amount: 10
  },
  {
    type: "apples",
    amount: 0,
  }, {
    type: "oranges",
    amount: 5
  }
]

const endresult = Object.values(fruits.reduce((value, object) => {
  if (value[object.type]) {
    ['marks'].forEach(key => value[object.type][key] = value[object.type][key]   object[key]);
  } else {
    value[object.type] = { ...object
    };
  }
  return value;
}, {}));

console.log(endresult)

I'm not sure what I'm doing wrong and how can I add the new key-value pair to count the times the object is present in the array? Could someone point me in the right direction? Thanks!

CodePudding user response:

Your code looks more complex than what is required. Somewhere you must be adding an undefined to a number and hence getting NaN(not a number).

Also :

  1. you are not initializing the count property.
  2. you are not adding the amount and count, in the if condition.

Making a few changes to your code itself this can be fixed:

const fruits = [{
    type: "oranges",
    amount: 10
  },
  {
    type: "apples",
    amount: 0,
  }, {
    type: "oranges",
    amount: 5
  }
]

const endresult = Object.values(fruits.reduce((value, object) => {
  if (value[object.type]) {
    value[object.type].amount  = object.amount; 
    value[object.type].count  ;

} else {
    value[object.type] = { ...object , count : 1
    };
  }
  return value;
}, {}));

console.log(endresult)

CodePudding user response:

You can easily achieve the result using Map, reduce, and Array.from

const fruits = [
  {
    type: "oranges",
    amount: 10,
  },
  {
    type: "apples",
    amount: 0,
  },
  {
    type: "oranges",
    amount: 5,
  },
];

const endresult = Array.from(
  fruits
    .reduce((map, curr) => {
      if (!map.has(curr.type)) map.set(curr.type, { ...curr, count: 1 });
      else {
        map.get(curr.type).amount  = curr.amount;
        map.get(curr.type).count  ;
      }
      return map;
    }, new Map())
    .values()
);

console.log(endresult);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

This reduce works better

const fruits = [{ type: "oranges", amount: 10 }, { type: "apples", amount: 0}, { type: "oranges", amount: 5 }]

const endresult = fruits.reduce((acc,fruit) => {
  acc[fruit.type] = acc[fruit.type]  || fruit;
  const theFruit = acc[fruit.type]
  theFruit.count = !!theFruit.count ? theFruit.count : 0;
  theFruit.count  
  theFruit.amount  = fruit.amount 
  return acc;
}, {});

console.log(Object.values(endresult))

  • Related