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!
- Use Destructuring Assignment
const { apples, oranges } = cur.summary.totals;
- 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)