Reputation: 1285
I have an array of JavaScript objects, that look something like this.
[ { 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 } ]
I want to loop through this array and remove any duplicate objects of the same name, while adding their values together. In basic terms:
[ { name: "A", value: 200 },
{ name: "B", value: 90 },
{ name: "C", value: 80 } ]
I have an idea of how to go about this, pseudo-code:
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
I feel this is very inefficient. Is there any better way of going about this?
Upvotes: 2
Views: 101
Reputation: 3662
You can use the reduce function.
Note that for simplicity the sums are gathered as an associative array (grouped by name
) and then the values retrieved to match your expected result.
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);
Upvotes: 1
Reputation: 12637
What language is this? this ain't JS.
in JS I would write it like that:
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 */});
Upvotes: -1
Reputation: 1965
You're looking for reduce
and object-based indexing:
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)
Upvotes: 0
Reputation: 122027
You can do this with forEach()
loop and thisArg
parameter.
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)
Upvotes: 1
Reputation: 1409
I would use a temporary object as an intermediary state, and then create a new array based on that object:
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);
Upvotes: 3
Reputation: 1123
You could create a temporary "associative array" and iterate through the array of objects like
var temp = [];
for(var i = 0; i < A.length; i++) {
temp[A[i].name] += A[i].value;
}
A = temp;
If you're trying to keep A
as an actual array, then look at @TAGraves answer for the extra bit to convert it into an actual array.
Upvotes: 0