Tpircsnart
Tpircsnart

Reputation: 47

JS: how to merge arrays with objects without duplicates

let arrayFirst = [{name: 'a', num: 1}, { name: 'b', num: 1} ]
let arraySecond = [{name: 'a', num: 1}, { name: 'b', num: 1} ]
let arrayThid = [{name: 'a', num: 1}, { name: 'c', num: 1} ]

... ... ...

expected output:

[{name: 'a', num: 3}, { name: 'b', num: 2}, { name: 'c', num: 1} ]

I only found array inner object sum up, but how about arrays sum up by its object key-value?

Upvotes: 0

Views: 214

Answers (7)

StepUp
StepUp

Reputation: 38199

You can use reduce method:

const result = arrayFirst.concat(arraySecond).concat(arrayThid).reduce((a, c) => {
  a[c.name] = a[c.name] || {name: c.name, num: 0};
  a[c.name].num += c.num;
  return a;
}, {});

An example:

let arrayFirst = [{name: 'a', num: 1}, { name: 'b', num: 1} ]
let arraySecond = [{name: 'a', num: 1}, { name: 'b', num: 1} ]
let arrayThid = [{name: 'a', num: 1}, { name: 'c', num: 1} ]

const result = arrayFirst.concat(arraySecond).concat(arrayThid).reduce((a, c) => {
  a[c.name] = a[c.name] || {name: c.name, num: 0};
  a[c.name].num += c.num;
  return a;
}, {});

console.log(Object.values(result));

Upvotes: 0

Ele
Ele

Reputation: 33726

You can use the function reduce for grouping the values and the function Object.values for extracting the grouped values as an array.

let arrayFirst = [{name: 'a', num: 1}, { name: 'b', num: 1} ];
let arraySecond = [{name: 'a', num: 1}, { name: 'b', num: 1} ];
let arrayThid = [{name: 'a', num: 1}, { name: 'c', num: 1} ];

let result = Object.values(arrayFirst.concat(arraySecond).concat(arrayThid).reduce((a, {name, num}) => {
  (a[name] || (a[name] = {name, num: 0})).num += num;
  return a;
}, Object.create(null)));

console.log(result);

Upvotes: 0

César Vega
César Vega

Reputation: 1

Also, you can cache the results in object:

const addSumToCachedNum = (acc, item) => {
    const { name, num } = item;
    const current = acc[name] || {};
    const currentNum = current.num || 0;

    acc[name] = {
      name,
      num: currentNum + num,
    };

    return acc;
}

const sumArrayByKey = (...items) => {
    const mergedArray = [].concat(...items);
    const sumObject = mergedArray.reduce(addSumToCachedNum, {});

    return Object.values(sumObject);
};

Upvotes: 0

baao
baao

Reputation: 73271

You can use below function to group and sum the values. The method takes as many arrays (or objects) as you want and sums them based on groupby (name in your case) and sumkey

function sumArrays(groupby, sumkey, ...arrays) {
  return [...arrays.flat().reduce((a, b) => a.set(b[groupby], (a.get(b[groupby]) || 0) + b[sumkey]), new Map())].map(([k, v]) => ({
    [groupby]: k,
    [sumkey]: v
  }))
}

console.log(sumArrays('name', 'num', arrayFirst, arraySecond, arrayThid));
<script>
arrayFirst = [{
  name: 'a',
  num: 1
}, {
  name: 'b',
  num: 1
}]
let arraySecond = [{
  name: 'a',
  num: 1
}, {
  name: 'b',
  num: 1
}]
let arrayThid = [{
  name: 'a',
  num: 1
}, {
  name: 'c',
  num: 1
}]
</script>

Upvotes: 3

xmk-dev
xmk-dev

Reputation: 21

In my opinion @baao answer is great and generic. However if you want something simpler try:

[arrayFirst, arraySecond, arrayThird].flat().filter((item, index, array) => array.findIndex(i => (i.name === item.name)) === index)

or if you want check whole objects in arrays you could use

[arrayFirst, arraySecond, arrayThird].flat().filter((item, index, array) => array.findIndex(i => (JSON.stringify(i) === JSON.stringify(item))) === index)

Upvotes: 0

Prashant Pimpale
Prashant Pimpale

Reputation: 10717

You can do with the help of Array.concat and findIndex:

let arrayFirst = [{
    name: 'a',
    num: 1
}, {
    name: 'b',
    num: 1
}]
let arraySecond = [{
    name: 'a',
    num: 1
}, {
    name: 'b',
    num: 1
}]
let arrayThid = [{
    name: 'a',
    num: 1
}, {
    name: 'c',
    num: 1
}]

var result = [];

arrayThid.concat((arrayFirst.concat(arraySecond))).forEach(function(obj) {
    let index = result.findIndex(x => x.name === obj.name);
    if (index == -1) {
        result.push(obj);
    } else {
        result[index].num += obj.num;
    }
});

console.log(result)

Upvotes: 0

Wang Liang
Wang Liang

Reputation: 4444

let arrayFirst = [{ name: 'a', num: 1 }, { name: 'b', num: 1 }]
let arraySecond = [{ name: 'a', num: 1 }, { name: 'b', num: 1 }]
let arrayThid = [{ name: 'a', num: 1 }, { name: 'c', num: 1 }]

// [{name: 'a', num: 3}, { name: 'b', num: 2}, { name: 'c', num: 1} ]
var r = {}

addObject = (arrayObj) => {
    arrayObj.forEach(first => {
        if (r[first.name] == null) r[first.name] = 0;
        r[first.name] += first.num
    })
}

addObject(arrayFirst)
addObject(arraySecond)
addObject(arrayThid)

console.log(r)
var result = []

Object.keys(r).forEach(key => {
    result.push({ name: key, num: r[key] })
});

Upvotes: 0

Related Questions