2013-10-07 6 views
6

Jak należałoby podjąć javascript tablicę obiektów, takich jak:Suma wartości javascript obiekt propertyA z samego obiektu propertyB w tablicę obiektów

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

zduplikowanych kluczy przez zsumowanie wartości. Aby uzyskać coś takiego:

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

Próbowałem iteracji i dodanie do nowej tablicy, ale to nie działa:

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 
+0

Dlaczego robisz 'key = Object.keys (pozycja) [0]; item = item [key]; '? Już wiesz, że nazwa to 'klucz', więc po prostu wykonaj' item.key' lub 'objArr [i] .key'. Ponadto użycie indeksu '[0]' niekoniecznie zawsze da tę samą właściwość. – user2736012

Odpowiedz

8

You należy przypisać każdy obiekt, który nie został znaleziony do wyniku, z jego właściwością .key.

Jeśli zostanie znaleziony, musisz dodać jego .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]); 

Również część problemu było to, że były ponowne zmienną item aby odwołać wartość .key, więc utracone odwołanie do obiektu.

3
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/

+0

OP chce mieć te same pary klucz/wartość, ale z "wartością" skonsolidowaną. – user2736012

0

Oto alternatywa dla ciebie, ale podobna do tej z Explosion Pills, wykorzystuje oryginalną tablicę zamiast tworzyć nową lub inny obiekt. Ten rodzaj może nie być konieczny i spowolni trochę, ale może zostać usunięty.

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

I jsperf który porównuje ten (z lub bez sortowania) przeciwko przyjętym odpowiedź. Możesz poprawić test wydajności, rozszerzając zestaw danych.

4

Zamiast za pomocą pętli for i popychając wartości, można korzystać bezpośrednio map i reduce:

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);

0

można również spróbować użyć javascript ramy linq, która jest dokładnie taka sama jak sql który jest podany pożądany wynik z mniej napisany kod i skuteczne i znaleźć na 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);
<script src="http://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.min.js"></script>

co jest całkiem łatwe w porównaniu do pętli. Mam nadzieję, że to może pomóc.

3

Możesz użyć tabeli mieszania do grupowania przez 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);

Powiązane problemy