JavaScript:使用类似属性对对象进行分组

时间:2016-08-10 12:36:39

标签: javascript

我有一个JavaScript对象数组,看起来像这样。

[ { name: "A", value: 50 },
  { name: "B", value: 20 }, 
  { name: "C", value: 30 }, 
  { name: "A", value: 40 }, 
  { name: "A", value: 50 }, 
  { name: "B", value: 70 }, 
  { name: "A", value: 10 }, 
  { name: "C", value: 50 } ]

我想循环遍历此数组并删除任何具有相同名称的重复对象,同时将它们的值相加。基本来说:

[ { name: "A", value: 200 },
  { name: "B", value: 90  }, 
  { name: "C", value: 80  } ]

我知道如何解决这个问题,伪代码:

for each object Obj in array A
    current = Obj
    for(i = (Obj's index + 1); i < A.length; i++)
        if(A[i].name = Obj.name) 
            Obj.value += A[i].value
            delete A[i]
        endif
    endfor
endfor

我觉得这是非常低效的。有没有更好的方法来解决这个问题?

6 个答案:

答案 0 :(得分:3)

我会使用临时对象作为中间状态,然后基于该对象创建一个新数组:

var arr = [ { name: "A", value: 50 },
  { name: "B", value: 20 }, 
  { name: "C", value: 30 }, 
  { name: "A", value: 40 }, 
  { name: "A", value: 50 }, 
  { name: "B", value: 70 }, 
  { name: "A", value: 10 }, 
  { name: "C", value: 50 } ];

var tempObj = arr.reduce(function (newObj, obj) {
    if (newObj[obj.name]) {
        newObj[obj.name] += obj.value;
    } else {
        newObj[obj.name] = obj.value;
    }
    return newObj;
}, {});

console.log(tempObj);

var result = [];

for (var i in tempObj) {
    result.push({
        name: i,
        value: tempObj[i]
    });
}

console.log(result);

答案 1 :(得分:1)

您可以使用forEach()循环和thisArg参数执行此操作。

&#13;
&#13;
var data = [ { name: "A", value: 50 },
  { name: "B", value: 20 }, 
  { name: "C", value: 30 }, 
  { name: "A", value: 40 }, 
  { name: "A", value: 50 }, 
  { name: "B", value: 70 }, 
  { name: "A", value: 10 }, 
  { name: "C", value: 50 } ];
  
var result = [];
data.forEach(function(e) {
  if (!this[e.name]) {
    this[e.name] = e;
    result.push(this[e.name]);
  } else {
    this[e.name].value += e.value;
  }
}, {});

console.log(result)
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以使用reduce function

请注意,为简单起见,将总和收集为关联数组(按name分组),然后检索值以匹配预期结果。

var arr = [ { name: "A", value: 50 },
  { name: "B", value: 20 }, 
  { name: "C", value: 30 }, 
  { name: "A", value: 40 }, 
  { name: "A", value: 50 }, 
  { name: "B", value: 70 }, 
  { name: "A", value: 10 }, 
  { name: "C", value: 50 } ];

var sums = arr.reduce(function (acc, curr) { 
  if(acc[curr.name]) {
    acc[curr.name].value += curr.value;
  } else {
    acc[curr.name] = curr;
  }
  
  return acc;
}, {});

var res = Object.keys(sums).map(function (key) {
    return sums[key];
});

console.log(res);

答案 3 :(得分:0)

您可以创建一个临时的“关联数组”并遍历像

这样的对象数组
var temp = [];
for(var i = 0; i < A.length; i++) {
    temp[A[i].name] += A[i].value;
}
A = temp;

如果您尝试将A保留为实际数组,请查看@TAGraves的额外位代码,以将其转换为实际数组。

答案 4 :(得分:0)

您正在寻找reduce和基于对象的索引:

var arr = [ { name: "A", value: 50 },
  { name: "B", value: 20 }, 
  { name: "C", value: 30 }, 
  { name: "A", value: 40 }, 
  { name: "A", value: 50 }, 
  { name: "B", value: 70 }, 
  { name: "A", value: 10 }, 
  { name: "C", value: 50 } ]

var accumulated = arr.reduce(function(accumulator, element) {
     var currentValue = accumulator[element.name];
     if(currentValue !== undefined) {
         accumulator[element.name] = currentValue + element.value;
     } else {
         accumulator[element.name] = element.value;
     }
     return accumulator;
}, {})

var result = Object.keys(accumulated).map(function(k) {return {name: k, value: accumulated[k]}})
console.log(result)

答案 5 :(得分:-1)

这是什么语言?这不是JS。

在JS中,我会这样写:

array = array.filter(function(item){
    //check wether there's already an cached item for this name
    if(item.name in this){
        //then add the value to the cached item
        this[item.name].value += item.value;
        //and remove the current item from the result
        return false;
    }else{
        //otherwise cache this item
        this[item.name] = item;
        //and keep it in the result
        return true;
    }
}, {/* abusing `this` as a cache */});