javascript – 按数组中的多个属性对对象进行分组,然后汇总它们的值

Grouping elements in array by multiple properties是与我的问题最接近的匹配,因为它确实通过数组中的多个键对对象进行分组.问题是这个解决方案没有总结属性值然后删除重复项,而是将所有重复项嵌入二维数组中.

预期的行为

我有一个对象数组,必须按形状和颜色分组.

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

仅当它们的形状和颜色相同时,此数组中的对象才被视为重复.如果是,我想分别总结其used和实例值,然后删除重复项.

因此,在此示例中,结果数组可能只包含四种组合:方形红色,方形蓝色,圆形红色,圆形蓝色

问题

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

var arr = [
    {shape: 'square',instances: 2}
];

result = [];

arr.forEach(function (a) {
    if ( !this[a.color] && !this[a.shape] ) {
        this[a.color] = { color: a.color,shape: a.shape,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",instances: 4}]

而不是预期的结果:

[{shape: "square",used: 5,instances: 3},{shape: "square",instances: 0}]

如何使我的功能按形状和颜色正确分组对象?即总结他们的价值并删除重复?

解决方法

Array#reduce与辅助对象一起使用以对类似对象进行分组.对于每个对象,检查帮助器中是否存在组合的形状和颜色.如果没有,请使用 Object#assign添加到帮助程序以创建对象的副本,然后推送到该数组.如果是,请将其值添加到used和instances.
var arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","used":2,{"shape":"circle","color":"blue","used":0,"instances":0},"used":4,"instances":4},"instances":5},"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收集值,然后在spreading Map#values将其转换回数组:

const arr = [{"shape":"square","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);

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...