0

I asked a similar question earlier today, but the output of this question is different. I asked wrongly the first time :(

I have a large array, which I have simplified for the question purpose

[
  {"item1": 3, "item40": 2},
  {"item1": 4, "item40": 8}
]

I would like to end up with this, which is the sum of each similar property in the array of objects. I tried a lot. Doing a forEach whith a forIn inside. But I am stuck. Please help :)

[7, 10]

1
  • Afaik, the order of properties in JS objects is not always guaranteed. Therefor you can't be 100% sure in your example ([7,10]) which is the sum of item1 and which is the sum of item40. You could either use a Map or retain the props during summation. See stackoverflow.com/questions/5525795/… Commented Jan 14, 2021 at 19:06

5 Answers 5

1

let arr = [
    {"item1": 3, "item40": 2},
    {"item1": 4, "item40": 8}
  ]
  
const res = Object.keys(arr[0]).map(key => arr.reduce((acc, cur) => acc + parseInt(cur[key] || 0), 0))
  
console.log(res)

Sign up to request clarification or add additional context in comments.

3 Comments

what if one of the values are empty. let arr = [ {"item1": '3', "item40": '2'}, {"item1": '4', "item40": ''} ] [7, 2]
Just add edge case handling
Clever, but why use parseInt?
1

You first need to get a set of keys across all the data items, as the order and appearance of each key may differ from each item in the data array.

Then you can map the keys to a reduction across all the items.

const data = [ { "item1": 3, "item40": 2 }, { "item1": 4, "item40": 8 } ];

const keys = [...new Set(data.reduce((keys, obj) =>
  [...keys, ...Object.keys(obj)], []))];
  
const summary = keys.map((key) =>
  data.reduce((acc, item) => acc + (item[key] || 0), 0));

console.log(summary); // [ 7, 10 ]

It is better to retain the key-value pairs though...

const data = [ { "item1": 3, "item40": 2 }, { "item1": 4, "item40": 8 } ];

const keys = [...new Set(data.reduce((keys, obj) =>
  [...keys, ...Object.keys(obj)], []))];
  
const summary = keys.map((key) => ({
  key,
  value: data.reduce((acc, item) => acc + (item[key] || 0), 0)
}));

// [{"key": "item1", "value": 7}, {"key": "item40", "value": 10}]
console.log(summary);

Update Here is a better version. You reduce the items, and for each item, you reduce the keys.

const data = [ { "item1": 3, "item40": 2 }, { "item1": 4, "item40": 8 } ];

const keys = [...new Set(data.reduce((keys, obj) =>
  [...keys, ...Object.keys(obj)], []))];

const summary = data.reduce((values, item) =>
  keys.reduce((acc, key) =>
    ({ ...acc, [key]: acc[key] + (item[key] || 0)})
  , values
, {}));

console.log(summary); // { "item1": 7, "item40": 10 }
console.log(Object.values(summary)); // [ 7, 10 ]

Comments

0

If you're open to external modules, you can do this quite nicely with lodash's _.sumBy:

const data = [
  { item1: 3, item2: 4, item40: 2 },
  { item1: 4, item2: 4, item40: 8 },
];

let output = {} // final result stored here
let keys = _.keys(data[0]) // or Object.keys(data[0]) // using the first object as a template to see what keys to search for
keys.forEach(key => output[key] = _.sumBy(data, key)) // sum them up

document.write(`<pre>${JSON.stringify(output, null, 4)}</pre>`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

It doesn't matter whether objects past data[0] are missing keys or have additional ones, but note that only the keys found in data[0] will be summed

Comments

0

Here's a version that uses Map to maintain the sequence of the object properties:

const data = [{
    item1: 3,
    item40: 2
  },
  {
    item1: 4,
    item40: 8
  },
];

const arr =

  // Array.from converts iterator from values() below to array
  Array.from(

    data
    .reduce((map, obj) => {

      // accumulate each object's values into map
      Object.entries(obj).forEach(([propName, value]) => {
        map.set(propName, (map.get(propName) ? ? 0) + value);
      });

      return map;
    }, new Map())

    // extract all values from map into an iterator
    .values()
  );

console.log(arr); // [ 7, 10 ]

Comments

0

 
const itemsArray =  [
  { item1: 3, item2: 4, item40: 2 },
  { item1: 4, item2: 4, item40: 8 },
];

const sums = {};

for (const obj of itemsArray) {
 
  for (const key in obj) {
   
    if (!sums[key]) {
      sums[key] = 0;
    }
 
    sums[key] += +obj[key] || 0;
  }
}
const result = Object.values(sums);

console.log(result); // Output: [7, 8, 10]

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.