当前位置: 首页 > 知识库问答 >
问题:

按数组中的多个属性对对象进行分组,然后将其值相加

双志强
2023-03-14

按多个属性对数组中的元素进行分组最符合我的问题,因为它确实是按数组中的多个键对对象进行分组的。问题是,这种解决方案不求和属性值,然后删除重复项,而是将所有重复项嵌套在二维数组中。

预期行为

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

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 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}]

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

共有3个答案

陈昂熙
2023-03-14

可以使用哈希表和键对相同的组进行分组。

var array = [{ 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 }],
    hash = Object.create(null),
    grouped = [];
    
array.forEach(function (o) {
    var key = ['shape', 'color'].map(function (k) { return o[k]; }).join('|');
    
    if (!hash[key]) {
        hash[key] = { shape: o.shape, color: o.color, used: 0, instances: 0 };
        grouped.push(hash[key]);
    }
    ['used', 'instances'].forEach(function (k) { hash[key][k] += o[k]; });
});

console.log(grouped);
css prettyprint-override">.as-console-wrapper { max-height: 100% !important; top: 0; }
倪举
2023-03-14

使用此方法可以指定多个属性:

 public static groupBy(array, f) {
       let groups = {};
       array.forEach(function (o) {
         var group = JSON.stringify(f(o));
         groups[group] = groups[group] || [];
         groups[group].push(o);
       });
    return Object.keys(groups).map(function (group) {
      return groups[group];
    })
 }

将此方法称为:

var result = Utils.groupBy(arr, function (item) {
            return [item.shape, item.color];
          });
乐正育
2023-03-14

将Array#reduce与辅助对象一起使用,将相似的对象分组。对于每个对象,检查辅助对象中是否存在组合的形状颜色。如果没有,请使用Object#assign添加到辅助对象,以创建对象的副本,并推送到数组。如果有,则将其值添加到已用实例

js lang-js prettyprint-override">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);
 类似资料:
  • 问题内容: 通过多个属性对数组中的元素进行分组最符合我的问题,因为它确实通过数组中的多个键对对象进行了分组。问题是此解决方案无法汇总属性值,然后删除重复项,而是将所有重复项嵌套在二维数组中。 预期行为 我有一个对象数组,必须按和进行分组。 这个数组中的对象被视为重复仅当其和是相同的。如果它们是,我想分别总结它们的和值,然后删除重复项。 因此,在这个例子的结果阵列可以仅含有四种组合:,,, 问题 我

  • 我已经设法编写了一个使用Java8Streams API的解决方案,该解决方案首先按对象路由的值对其列表进行分组,然后对每组中的对象数进行计数。它返回映射路由->long。代码如下: 和路由类: 应转换为: 请注意,映射的键数为2条路由,它是lastUpdated值最大的一条。

  • 问题内容: 我设法使用Java 8 Streams API编写了一个解决方案,该解决方案首先按其值对对象Route列表进行分组,然后对每个组中的对象数进行计数。它返回一个映射Route-> Long。这是代码: 和Route类: 我还想实现的是,每个组的密钥都是lastUpdated值最大的密钥。我已经在研究此解决方案,但是我不知道如何组合计数和按值分组以及路由最大lastUpdated值。这是我

  • 问题内容: 我已经使用AJAX获得了以下对象并将它们存储在数组中: 如何仅使用JavaScript 创建一个函数以按属性 升序 或 降序 对对象进行排序? 问题答案: 按价格升序对房屋进行排序: 或在ES6版本之后:

  • 这是我的输入,我有一个数组,其中名称键在多个对象中具有值“Foo1”,因此我希望在单独的数组中相对于“name”键值和其他信息的唯一对象。 下面的数组是唯一的名称键和其他值和状态键从所有匹配的对象存储在new_obj键。

  • 我想按属性对对象列表进行分组,然后使用(Key,Value)对迭代结果。 我在Java8中找到了用一个属性对对象列表进行分组的方法,如下所示 但结果将只有条目集(在entrySet属性中有值)。键集和值集将具有空值。我想迭代如下内容