Soma javascript object propertyA valores com o mesmo object propertyB no array de objects

Como alguém pegaria uma matriz javascript de objects como:

my objArr = [ {key:Mon Sep 23 2013 00:00:00 GMT-0400, val:42}, {key:Mon Sep 24 2013 00:00:00 GMT-0400, val:78}, {key:Mon Sep 25 2013 00:00:00 GMT-0400, val:23}, {key:Mon Sep 23 2013 00:00:00 GMT-0400, val:54}] 

e mesclar chaves duplicadas sumndo os valores. Para obter algo assim:

 my reducedObjArr = [ {key:Mon Sep 23 2013 00:00:00 GMT-0400, val:96}, {key:Mon Sep 24 2013 00:00:00 GMT-0400, val:78}, {key:Mon Sep 25 2013 00:00:00 GMT-0400, val:23}] 

Eu tentei iterar e adicionar a uma nova matriz, mas isso não funcionou:

 var reducedObjArr = []; var item = null, key = null; for(var i=0; i<objArr.length; i++) { item=objArr[i]; key = Object.keys(item)[0]; item=item[key]; if(!result[key]){ result[key] = item; }else{ result[key] += item;} }a 

Você deve estar atribuindo cada object não encontrado ao resultado com sua propriedade .key .

Se for encontrado, você precisará adicionar seu .val .

 var temp = {}; var obj = null; for(var i=0; i < objArr.length; i++) { obj=objArr[i]; if(!temp[obj.key]) { temp[obj.key] = obj; } else { temp[obj.key].val += obj.val; } } var result = []; for (var prop in temp) result.push(temp[prop]); 

Além disso, parte do problema era que você estava reutilizando a variável de item para fazer referência ao valor de .key , portanto, você perdeu a referência ao object.

Em vez de usar um loop for e empurrar valores, você pode usar diretamente o mapa e reduzir :

 let objArr = [ {key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 42}, {key: 'Mon Sep 24 2013 00:00:00 GMT-0400', val: 78}, {key: 'Mon Sep 25 2013 00:00:00 GMT-0400', val: 23}, {key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 54} ]; // first, convert data into a Map with reduce let counts = objArr.reduce((prev, curr) => { let count = prev.get(curr.key) || 0; prev.set(curr.key, curr.val + count); return prev; }, new Map()); // then, map your counts object back to an array let reducedObjArr = [...counts].map(([key, value]) => { return {key, value} }) console.log(reducedObjArr); 

Você poderia usar uma tabela de hash para o agrupamento por key .

 var array = [{ key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 42 }, { key: 'Mon Sep 24 2013 00:00:00 GMT-0400', val: 78 }, { key: 'Mon Sep 25 2013 00:00:00 GMT-0400', val: 23 }, { key: 'Mon Sep 23 2013 00:00:00 GMT-0400', val: 54}], grouped = []; array.forEach(function (o) { if (!this[o.key]) { this[o.key] = { key: o.key, val: 0 }; grouped.push(this[o.key]); } this[o.key].val += o.val; }, Object.create(null)); console.log(grouped); 
 var targetObj = {}; for (var i = 0; i < objArr.length; i++) { if (!targetObj.hasOwnProperty(objArr[i].key)) { targetObj[objArr[i].key] = 0; } targetObj[objArr[i].key] += objArr[i].val; } 

http://jsfiddle.net/HUMxp/

Aqui está uma alternativa para você, mas semelhante à das Pílulas de Explosão , reutiliza a matriz original em vez de criar uma nova ou um object diferente. O tipo pode não ser necessário e atrasará um pouco as coisas, mas poderá ser removido.

Javascript

 function reduceMyObjArr(arr) { var temp = {}, index; for (index = arr.length - 1; index >= 0; index -= 1) { key = arr[index].key; if (temp.hasOwnProperty(key)) { arr[temp[key]].val += arr[index].val; arr.splice(index, 1); } else { temp[key] = index; } } arr.sort(function (a, b) { if (a.key === b.key) { return 0; } if (a.key < b.key) { return -1; } return 1; }); return arr; } var myObjArr = [{ key: "Mon Sep 23 2013 00: 00: 00 GMT - 0400", val: 42 }, { key: "Mon Sep 24 2013 00: 00: 00 GMT - 0400", val: 78 }, { key: "Mon Sep 25 2013 00: 00: 00 GMT - 0400", val: 23 }, { key: "Mon Sep 23 2013 00: 00: 00 GMT - 0400", val: 54 }]; reduceMyObjArr(myObjArr); console.log(myObjArr); 

jsFiddle

E um jsperf que compara isso (com e sem o tipo) contra a resposta aceita. Você pode melhorar o teste de desempenho estendendo o dataset.

você também pode tentar usar o javascript linq framework que é exatamente o mesmo que a instrução sql que recebe a saída desejada com menos código escrito e efetivo e encontrado em linq.js

 var objArr = [ {key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:42}, {key:'Mon Sep 24 2013 00:00:00 GMT-0400', val:78}, {key:'Mon Sep 25 2013 00:00:00 GMT-0400', val:23}, {key:'Mon Sep 23 2013 00:00:00 GMT-0400', val:54} ]; var aggregatedObject = Enumerable.From(objArr) .GroupBy("$.key", null, function (key, g) { return { key: key, contributions: g.Sum("$.val") } }) .ToArray(); console.log(aggregatedObject);