Reputation: 3
this is my objects array -
var items = [{category: "", sum: 687355.25},
{category: "", sum: 526335.4},
{category: "building, general work and whitewashing", sum: 991844},
{category: "Mining and quarrying of non metal minerals", sum: 566317.64},
{category: "wholesale: marble stone for building", sum: 1100391.64},
{category: "heavy building contracting, infrastructure work contractor", sum: 600000},
{category: "building and construction contractor", sum: 829142.67},
{category: "building and construction contractor", sum: 952417},
{category: "building and construction contractor, general", sum: 731128},
{category: "building and construction contractor, general", sum: 708000},
{category: "building and construction contractor, institutions and public buildings", sum: 542540},
{category: "retail: womens clothing stores", sum: 540000},
{category: "retail: gas stations", sum: 567000},
{category: "financing - banks and foreign currency", sum: 700000},
{category: "financing - banks and checks clearing agencies", sum: 526950},
{category: "real estate projects launching", sum: 1084839.77},
{category: "real estate sales, lease and rental", sum: 650000},
{category: "real estate services purchase agents", sum: 1147500},
{category: "real estate development", sum: 534000},
{category: "services: financial services", sum: 735000}]
I would like to get this result -
modifiedItems = [{category: "", sum: 1213690.65}
{category: "building, general work and whitewashing", sum: 991844},
{category: "Mining and quarrying of non metal minerals", sum: 566317.64},
{category: "wholesale: marble stone for building", sum: 1100391.64},
{category: "heavy building contracting, infrastructure work contractor", sum: 600000},
{category: "building and construction contractor", sum: 1781559.67}
{category: "building and construction contractor, general", sum: 1439128}
{category: "building and construction contractor, institutions and public buildings", sum: 542540},
{category: "retail: womens clothing stores", sum: 540000},
{category: "retail: gas stations", sum: 567000},
{category: "financing - banks and foreign currency", sum: 700000},
{category: "financing - banks and checks clearing agencies", sum: 526950},
{category: "real estate projects launching", sum: 1084839.77},
{category: "real estate sales, lease and rental", sum: 650000},
{category: "real estate services purchase agents", sum: 1147500},
{category: "real estate development", sum: 534000},
{category: "services: financial services", sum: 735000}]
eliminating duplicate keys and summing the value of however many duplicates there are. I know i should use reduce, but just can't figure it out. Please help!
Upvotes: 0
Views: 1245
Reputation: 902
This can indeed be done using reduce:
results = items.reduce(sumFunction)
It is worth looking at the structure the end result will have. In this case it will be an array of objects. Reduce will build up (or accumulate) this result when it goes through all the items. the initial value to start the accumulation process will be an empty array. We pass this as the second parameter:
results = items.reduce(sumFunction, []);
But how do you write the sumFunction?
The sumFunction will be called with 3 parameters: a variable holding the temporary result (= the accumulator), the current item, and the index of the current item. The accumulator will gradually become more and more like the end result you want: an array of items.
Now we can write what should happen to the accumulator when each step gets passed to it:
function sumFunction (accumulator, currentItem, currentIndex) {
// look up if the current item is of a category that is already in our end result.
index = accumulator.findIndex((item) => item.category === currentItem.category)
if (index < 0) {
accumulator.push(currentItem); // now item added to the array
} else {
accumulator[index].sum += currenItem.sum // update the sum of already existing item
}
return accumulator;
}
or if you are using es5:
function sumFunction (accumulator, currentItem, currentIndex) {
// look up if the current item is of a category that is already in our end result.
index = accumulator.findIndex(function(item) { return (item.category === currentItem.category);});
if (index < 0) {
accumulator.push(currentItem); // now item added to the array
} else {
accumulator[index].sum += currenItem.sum // update the sum of already existing item
}
return accumulator;
}
Upvotes: 1
Reputation: 171
I think this should solve the problem. That is what I can come up with right now. I will edit it afterwards if I think of some better way.
var map = {};
var new_items = [];
var length=items.length;
for(var i=0;i<length;i++){
if(items[i]["category"] in map){
map[items[i]["category"]]+=items[i]["sum"];
}
else{
map[items[i]["category"]]=items[i]["sum"];
}
}
for(key in map){
new_items.push({"category":key,"sum":map[key]});
}
Basically I created a map of the category and sum values and then used it to construct a new array as required.
Upvotes: 0
Reputation: 191976
You can use Array#reduce with a helper object (dict
in the example). The helper object maintains a reference to categories that were already added. When an object contains a new category, add it to the array and the dict
object. If the object already exists in dict
add it's sum to the category sum.
var items = [{"category":"","sum":687355.25},{"category":"","sum":526335.4},{"category":"building, general work and whitewashing","sum":991844},{"category":"Mining and quarrying of non metal minerals","sum":566317.64},{"category":"wholesale: marble stone for building","sum":1100391.64},{"category":"heavy building contracting, infrastructure work contractor","sum":600000},{"category":"building and construction contractor","sum":829142.67},{"category":"building and construction contractor","sum":952417},{"category":"building and construction contractor, general","sum":731128},{"category":"building and construction contractor, general","sum":708000},{"category":"building and construction contractor, institutions and public buildings","sum":542540},{"category":"retail: womens clothing stores","sum":540000},{"category":"retail: gas stations","sum":567000},{"category":"financing - banks and foreign currency","sum":700000},{"category":"financing - banks and checks clearing agencies","sum":526950},{"category":"real estate projects launching","sum":1084839.77},{"category":"real estate sales, lease and rental","sum":650000},{"category":"real estate services purchase agents","sum":1147500},{"category":"real estate development","sum":534000},{"category":"services: financial services","sum":735000}];
var dict = Object.create(null); // create an empty object
var result = items.reduce(function(arr, o) {
var current = dict[o.category]; // get the object from dict
if(!current) { // if dict doesn't contain object
current = Object.assign({}, o); // create a clone of the object - this prevents changing the original object
arr.push(current); // push it to the array
dict[o.category] = current; // add it to dict
} else { // if dict contains the object
current.sum += o.sum; // update the sum
}
return arr;
}, []);
console.log(result);
Upvotes: 1