无副作用的嵌套对象的总和值(减少)
Sum values of nested objects without side-effects (reduce)
我正在尝试计算嵌套在食物对象中的营养价值:
[
{
id: 'Potato',
nutrition: [
{ id: 'PROT', val: 4 },
{ id: 'SUGAR', val: 1 }
]
},
{
id: 'Banana',
nutrition: [
{ id: 'FIB', val: 10 },
{ id: 'SUGAR', val: 4 }
]
}
]
我使用 Array.prototype.reduce() 这样做:
foods.reduce((acc, { nutrition }) => {
nutrition.map((x) => {
let current = acc.find((y) => y.id === x.id)
if (current) current.val += x.val
else acc.push(x)
})
return acc
}, [])
这行得通,但它操纵了我的原始数组,我不明白为什么。我曾尝试使用传播运算符和 let/var 但无济于事。我怎样才能实现我想要的而没有副作用?
你可以利用 reduce
和 forEach
最后取 Object.values
,像这样:
const foods = [ { id: 'Potato', nutrition: [ { id: 'PROT', val: 4 }, { id: 'SUGAR', val: 1 } ] }, { id: 'Banana', nutrition: [ { id: 'FIB', val: 10 }, { id: 'SUGAR', val: 4 } ] }];
const result = Object.values(foods.reduce((a,{nutrition})=>{
nutrition.forEach(({id, val})=>{
(a[id] ??= {id, val:0}).val+=val;
});
return a;
},{}));
console.log(result);
您可以首先使用 forEach
而不是 map
因为在您的用例中不需要 map
到 return 一个新数组并修复上面的方法是在推送到 acc
数组时制作 x
的副本,如下所示:-
foods.reduce((acc, { nutrition }) => {
nutrition.forEach((x) => {
let current = acc.find((y) => y.id === x.id)
if (current) current.val += x.val
else acc.push({...x})
})
return acc
}, [])
我正在尝试计算嵌套在食物对象中的营养价值:
[
{
id: 'Potato',
nutrition: [
{ id: 'PROT', val: 4 },
{ id: 'SUGAR', val: 1 }
]
},
{
id: 'Banana',
nutrition: [
{ id: 'FIB', val: 10 },
{ id: 'SUGAR', val: 4 }
]
}
]
我使用 Array.prototype.reduce() 这样做:
foods.reduce((acc, { nutrition }) => {
nutrition.map((x) => {
let current = acc.find((y) => y.id === x.id)
if (current) current.val += x.val
else acc.push(x)
})
return acc
}, [])
这行得通,但它操纵了我的原始数组,我不明白为什么。我曾尝试使用传播运算符和 let/var 但无济于事。我怎样才能实现我想要的而没有副作用?
你可以利用 reduce
和 forEach
最后取 Object.values
,像这样:
const foods = [ { id: 'Potato', nutrition: [ { id: 'PROT', val: 4 }, { id: 'SUGAR', val: 1 } ] }, { id: 'Banana', nutrition: [ { id: 'FIB', val: 10 }, { id: 'SUGAR', val: 4 } ] }];
const result = Object.values(foods.reduce((a,{nutrition})=>{
nutrition.forEach(({id, val})=>{
(a[id] ??= {id, val:0}).val+=val;
});
return a;
},{}));
console.log(result);
您可以首先使用 forEach
而不是 map
因为在您的用例中不需要 map
到 return 一个新数组并修复上面的方法是在推送到 acc
数组时制作 x
的副本,如下所示:-
foods.reduce((acc, { nutrition }) => {
nutrition.forEach((x) => {
let current = acc.find((y) => y.id === x.id)
if (current) current.val += x.val
else acc.push({...x})
})
return acc
}, [])