javascript 对对象数组中的相似键求和
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24444738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sum similar keys in an array of objects
提问by Sameer Joshi
I have an array of objects like the following:
我有一个对象数组,如下所示:
[
{
'name': 'P1',
'value': 150
},
{
'name': 'P1',
'value': 150
},
{
'name': 'P2',
'value': 200
},
{
'name': 'P3',
'value': 450
}
]
I need to add up all the values for objects with the same name. (Probably also other mathematical operations like calculate average.) For the example above the result would be:
我需要将同名对象的所有值相加。(可能还有其他数学运算,例如计算平均值。)对于上面的示例,结果将是:
[
{
'name': 'P1',
'value': 300
},
{
'name': 'P2',
'value': 200
},
{
'name': 'P3',
'value': 450
}
]
回答by link
First iterate through the array and push the 'name' into another object's property. If the property exists add the 'value' to the value of the property otherwise initialize the property to the 'value'. Once you build this object, iterate through the properties and push them to another array.
首先遍历数组并将“名称”推送到另一个对象的属性中。如果属性存在,则将“值”添加到属性的值,否则将属性初始化为“值”。构建此对象后,遍历属性并将它们推送到另一个数组。
Here is some code:
这是一些代码:
var obj = [
{ 'name': 'P1', 'value': 150 },
{ 'name': 'P1', 'value': 150 },
{ 'name': 'P2', 'value': 200 },
{ 'name': 'P3', 'value': 450 }
];
var holder = {};
obj.forEach(function(d) {
if (holder.hasOwnProperty(d.name)) {
holder[d.name] = holder[d.name] + d.value;
} else {
holder[d.name] = d.value;
}
});
var obj2 = [];
for (var prop in holder) {
obj2.push({ name: prop, value: holder[prop] });
}
console.log(obj2);
Hope this helps.
希望这可以帮助。
回答by Vignesh Raja
You can use Array.reduce()to accumulate results during each iteration.
您可以使用Array.reduce()在每次迭代期间累积结果。
var arr = [{'name':'P1','value':150},{'name':'P1','value':150},{'name':'P2','value':200},{'name':'P3','value':450}];
var result = arr.reduce(function(acc, val){
var o = acc.filter(function(obj){
return obj.name==val.name;
}).pop() || {name:val.name, value:0};
o.value += val.value;
acc.push(o);
return acc;
},[]);
console.log(result);
回答by Nick Parsons
Here's an approach that should work for any number of properties within your objects (they need to be the same in both objects for them to "group"). It involves iterating through your array and reducing it to an object which holds key-value pairs. Each key of the new object is a string of all your property values, and so, if your object key already exists then you know it is a duplicate, which means you can add the object's current value to the stored object. Finally, you can use Object.values()
to get the accumulated objects set in your reduced key-value pair object:
这是一种适用于对象中任意数量属性的方法(它们需要在两个对象中相同才能“分组”)。它涉及遍历您的数组并将其缩减为一个包含键值对的对象。新对象的每个键都是您所有属性值的字符串,因此,如果您的对象键已经存在,那么您就知道它是重复的,这意味着您可以将对象的当前值添加到存储的对象中。最后,您可以使用Object.values()
来获取减少的键值对对象中设置的累积对象:
const arr = [{'name':'P1','value':150},{'name':'P1','value':150},{'name':'P2','value':200},{'name':'P3','value':450}];
const res = Object.values(arr.reduce((acc, {value, ...r}) => {
const key = Object.entries(r).join('-');
acc[key] = (acc[key] || {...r, value: 0});
return (acc[key].value += value, acc);
}, {}));
console.log(res);
If you cannot support Object.entries()
or are working with nested objects, you can replace Object.entries()
with with JSON.stringify()
to stringify the object as a key:
如果您不能支持Object.entries()
或正在使用嵌套对象,您可以替换Object.entries()
withJSON.stringify()
将对象字符串化为键:
const arr = [{'name':'P1','value':150},{'name':'P1','value':150},{'name':'P2','value':200},{'name':'P3','value':450}];
const res = Object.values(arr.reduce((acc, {value, ...r}) => {
const key = JSON.stringify(r);
acc[key] = (acc[key] || {...r, value: 0});
return (acc[key].value += value, acc);
}, {}));
console.log(res);
回答by Akash
One more solution which is clean, I guess
我猜还有一种解决方案是干净的
var obj = [
{ 'name': 'P1', 'value': 150 },
{ 'name': 'P1', 'value': 150 },
{ 'name': 'P2', 'value': 200 },
{ 'name': 'P3', 'value': 450 }
];
var result = [];
Array.from(new Set(obj.map(x => x.name))).forEach(x => {
result.push(obj.filter(y => y.name === x).reduce((output,item) => {
let val = output[x] === undefined?0:output[x];
output[x] = (item.value + val);
return output;
},{}));
})
console.log(result);
回答by 200313
For some reason when I ran the code by @Vignesh Raja, I obtained the "sum" but also items duplicated. So, I had to remove the duplicates as I described below.
出于某种原因,当我通过@Vignesh Raja 运行代码时,我获得了“总和”,但也获得了重复的项目。因此,我必须删除重复项,如下所述。
Original array:
原始数组:
arr=[{name: "LINCE-01", y: 70},
{name: "LINCE-01", y: 155},
{name: "LINCE-01", y: 210},
{name: "MIRAFLORES-03", y: 232},
{name: "MIRAFLORES-03", y: 267}]
Using @VigneshRaja's code:
使用@VigneshRaja 的代码:
var result = arr.reduce(function(acc, val){
var o = acc.filter(function(obj){
return obj.name==val.name;
}).pop() || {name:val.name, y:0};
o.y += val.y;
acc.push(o);
return acc;
},[]);
console.log(result);
First outcome:
第一个结果:
result: [{name: "LINCE-01", y: 435},
{name: "LINCE-01", y: 435},
{name: "LINCE-01", y: 435},
{name: "MIRAFLORES-03", y: 499},
{name: "MIRAFLORES-03", y: 499}]
Removing the duplicates:
删除重复项:
var finalresult = result.filter(function(itm, i, a) {
return i == a.indexOf(itm);
});
console.log(finalresult);
Finally, I obtained what I whished:
最后,我得到了我想要的:
finalresult = [{name: "LINCE-01", y: 435},
{name: "MIRAFLORES-03", y: 657}]
Regards,
问候,