按数组中的多个属性对对象进行分组,然后将它们的值相加 [英] Group objects by multiple properties in array then sum up their values

查看:24
本文介绍了按数组中的多个属性对对象进行分组,然后将它们的值相加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按多个属性对数组中的元素进行分组是与我的问题最匹配,因为它确实通过数组中的多个键对对象进行分组.问题是这个解决方案没有总结属性值然后删除重复项,而是将所有重复项嵌套在一个二维数组中.

Grouping elements in array by multiple properties is the closest match to my question as it indeed groups objects by multiple keys in an array. Problem is this solution doesn't sum up the properties value then remove the duplicates, it instead nests all the duplicates in a two-dimensional arrays.

预期行为

我有一组对象,必须按 shapecolor 分组.

I have an array of objects which must be grouped by shape and color.

var arr = [
    {shape: 'square', color: 'red', used: 1, instances: 1},
    {shape: 'square', color: 'red', used: 2, instances: 1},
    {shape: 'circle', color: 'blue', used: 0, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 4},
    {shape: 'circle', color: 'red', used: 1, instances: 1},
    {shape: 'circle', color: 'red', used: 1, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 5},
    {shape: 'square', color: 'red', used: 2, instances: 1}
];

只有当 shapecolor 相同时,此数组中的对象才被视为重复对象.如果是,我想分别总结它们的 usedinstances 值,然后删除重复项.

Objects in this array are considered duplicates only if both their shape and color are the same. If they are, I want to respectively sum up their used and instances values then delete the duplicates.

所以在这个例子中,结果数组可能只包含四种组合:square redsquare bluecircle redcircle blue

So in this example result array may only contain four combinations : square red, square blue, circle red, circle blue

问题

我在这里尝试了一种更简单的方法:

I tried a simpler approach here:

var arr = [
    {shape: 'square', color: 'red', used: 1, instances: 1},
    {shape: 'square', color: 'red', used: 2, instances: 1},
    {shape: 'circle', color: 'blue', used: 0, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 4},
    {shape: 'circle', color: 'red', used: 1, instances: 1},
    {shape: 'circle', color: 'red', used: 1, instances: 0},
    {shape: 'square', color: 'red', used: 4, instances: 4},
    {shape: 'square', color: 'red', used: 2, instances: 2}
];

result = [];

arr.forEach(function (a) {
    if ( !this[a.color] && !this[a.shape] ) {
        this[a.color] = { color: a.color, shape: a.shape, used: 0, instances: 0 };
        result.push(this[a.color]);
    } 
    this[a.color].used += a.used;
    this[a.color].instances += a.instances;
}, Object.create(null));

console.log(result);

但它输出

[{shape: "square", color: "red", used: 11, instances: 9},
{shape: "circle", color: "blue", used: 4, instances: 4}]

而不是预期的结果:

[{shape: "square", color: "red", used: 5, instances: 3},
{shape: "circle", color: "red", used: 2, instances: 1},
{shape: "square", color: "blue", used: 11, instances: 9},
{shape: "circle", color: "blue", used: 0, instances: 0}]

如何让我的函数按形状和颜色正确分组对象?即总结它们的值并删除重复项?

How can I get my function to properly group the objects by shape and color ? i.e. sum up their values and remove the duplicates ?

推荐答案

使用 Array#reduce 带有一个辅助对象来对相似的对象进行分组.对于每个对象,检查组合的 shapecolor 是否存在于帮助程序中.如果没有,请使用 添加到帮助程序Object#assign 创建对象的副本,并推送到数组.如果是,请将其值添加到 usedinstances.

Use Array#reduce with a helper object to group similar objects. For each object, check if the combined shape and color exists in the helper. If it doesn't, add to the helper using Object#assign to create a copy of the object, and push to the array. If it does, add it's values to used and instances.

var arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];

var helper = {};
var result = arr.reduce(function(r, o) {
  var key = o.shape + '-' + o.color;
  
  if(!helper[key]) {
    helper[key] = Object.assign({}, o); // create a copy of o
    r.push(helper[key]);
  } else {
    helper[key].used += o.used;
    helper[key].instances += o.instances;
  }

  return r;
}, []);

console.log(result);

如果您可以使用 ES6,则使用 Map 收集值,然后通过 传播 地图#values:

If you can use ES6, you use a Map to collect the values, and then convert it back to an array by spreading the Map#values:

const arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];

const result = [...arr.reduce((r, o) => {
  const key = o.shape + '-' + o.color;
  
  const item = r.get(key) || Object.assign({}, o, {
    used: 0,
    instances: 0
  });
  
  item.used += o.used;
  item.instances += o.instances;

  return r.set(key, item);
}, new Map).values()];

console.log(result);

这篇关于按数组中的多个属性对对象进行分组,然后将它们的值相加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆