-2

I have an array of objects, where I want to find the objects having same value for name property and then merge them into single object by adding their values & subvalues.

const arr = [
 { id: 1, name: 'a', value: 2, subvalue: 3 }, 
 { id: 2, name: 'b', value: 4, subvalue: 3 },
 { id: 3, name: 'c', value: 4, subvalue: 3 },
 { id: 4, name: 'b', value: 3, subvalue: 4 } 
]

Expected output

[
 { id: 1, name: 'a', value: 2, subvalue: 3 }, 
 { id: 2, name: 'b', value: 7, subvalue: 7 },
 { id: 3, name: 'c', value: 4, subvalue: 3 }
]

The id of the new object can either be 2 or it can be 4. So it doesn't matter much. I have tried using filter, but not able to find a solution which suits my requirement

3

2 Answers 2

2

you can use reduce to group by name and then get the values array of the grouped object using Object.values

const arr = [
 { id: 1, name: 'a', value: 2, subvalue: 3 }, 
 { id: 2, name: 'b', value: 4, subvalue: 3 },
 { id: 3, name: 'c', value: 4, subvalue: 3 },
 { id: 4, name: 'b', value: 3, subvalue: 4 } 
]

const res = Object.values(arr.reduce((acc,curr) => {
  if(!acc[curr.name]){
    acc[curr.name] = curr
  } else {
    acc[curr.name].value += curr.value
    acc[curr.name].subvalue += curr.subvalue
  }
  return acc
},{}))

console.log(res)

or the whole if else logic be one-lined but less readable

const arr = [
 { id: 1, name: 'a', value: 2, subvalue: 3 }, 
 { id: 2, name: 'b', value: 4, subvalue: 3 },
 { id: 3, name: 'c', value: 4, subvalue: 3 },
 { id: 4, name: 'b', value: 3, subvalue: 4 } 
]

const res = Object.values(arr.reduce((acc, curr) => {
    acc[curr.name] = acc[curr.name] ? {...acc[curr.name], value: acc[curr.name].value + curr.value, subvalue: acc[curr.name].subvalue + curr.subvalue} : curr
    return acc
}, {}))

console.log(res)

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

1 Comment

You really posted a new group by answer?
1

Using only Array#reduce, see if the name of the current object is already present in the accumulator with Array#findIndex, then Values and Subvalues should be accumulated respectively with the current object Values and Subvalues, Otherwise add the current object in the accumulator:

const arr = [ { id: 1, name: 'a', value: 2, subvalue: 3 }, { id: 2, name: 'b', value: 4, subvalue: 3 }, { id: 3, name: 'c', value: 4, subvalue: 3 }, { id: 4, name: 'b', value: 3, subvalue: 4 } ];
const result = arr.reduce((acc, cur) => {
  const index = acc.findIndex((obj) => obj.name === cur.name);
  if (index !== -1) {
    acc[index] = {
      ...acc[index],
      value: acc[index].value + cur.value,
      subvalue: acc[index].subvalue + cur.subvalue,
    };
  } else {
    acc.push(cur);
  }
  return acc;
}, []);
console.log(result);

if you don't want to maintain the first (original) id and would rather use the id from the last (most recent) merged object, just replace ...acc[index] with ...cur when you merge them.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.