Reputation: 3365
I have an array that looks like this:
const values = [
{
value: 2000,
items: [
{
value: 300,
},
],
},
]
I want to sum the total of all of the values in values.value
, and if a values.items.value
exists I also want to include it in my sum.
values.reduce((total, obj) => obj.value + total, 0);
What would be the correct way to key into the nested array so it sums both the top and nested value
key in my reduce function? The output I'd like is 2300
but right now I can only get one level deep, and it's outputting 2000
.
Upvotes: 1
Views: 768
Reputation: 15130
You could nest your reduce
approach to handle the inner array while ensuring that the key exists in the inner array objects.
const values = [
{
value: 2000,
items: [
{
value: 300,
},
],
},
];
const total = values.reduce((acc, obj) => {
acc += obj.value;
acc += obj.items.reduce((a, o) => 'value' in o ? o.value + a : a, 0);
return acc;
}, 0);
console.log(total);
// 2300
Upvotes: 3
Reputation: 386600
You could iterate keys/values of the object and sum the a nested object and take the wanted key or zero as start value.
function sum(object, key) {
return Object.entries(object).reduce((s, [k, v]) => {
if (v && typeof v === 'object') return s + sum(v, key);
return s;
}, key in object ? object[key] : 0);
}
const values = [{ value: 2000, items: [{ value: 300 }] }];
console.log(sum(values, 'value'));
Upvotes: 0
Reputation: 17190
I will add an inner reduce()
to get the accumulated sum for the items
array. Also, I will add some checks with isNaN()
and Array.isArray()
just for safety:
const values = [
{value: 2000, items: [{value: 300}]},
{value: 3000},
{value: 2000, items: [{value: 300}, {foo: 20}]},
{nothing: "nothing"}
];
let res = values.reduce((acc, {value, items}) =>
{
acc += isNaN(value) ? 0 : value;
acc += Array.isArray(items) ?
items.reduce((sum, {value}) => sum + (isNaN(value) ? 0 : value), 0) :
0;
return acc;
}, 0);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Upvotes: 0
Reputation: 37755
You can use reduce add value and check for items
if it's there then add the value of items arrays as well
const values = [{value: 2000,items: [{value: 300,},],},]
let op = values.reduce((op,{value,items}) => {
op+= value
if(items && items.length) {
items.forEach(({value})=> op+=value )
}
return op
},0)
console.log(op)
Upvotes: 3