Reputation: 33
I have an array of objects and I am trying to consolidate the objects. I am trying to create a function that takes in the list as an argument and returns the new object.
function mergeValues(list) {
var obj = {};
list.forEach(item => {
if (!obj[item.state]) {
obj[item.state] = Object.assign({}, Object.keys(obj));
} else {
obj[item.state] = obj[item.state] + item.population;
}
});
return obj;
}
Current Input
var list = [
{ state: 'NJ', city: 'Newark', population: 150 },
{ state: 'NJ', city: 'Trenton', population: 200 },
{ state: 'NY', city: 'New York City', population: 500 },
{ state: 'MI', city: 'Detroit', population: 200 },
{ state: 'MI', city: 'Lansing', population: 100 }
];
Desired Output
var obj = {
MI: { count: 2, city: ['Detroit', 'Lansing'], population: 300 },
NJ: { count: 2, city: ['Newark', 'Trenton'], population: 350 },
NY: { count: 1, city: ['New York City'], population: 500 }
};
Edit: This is how I started, and am getting stuck. The key is returned with the state, but the values are being overridden with the most recent object.
function mergeValues(list) {
var obj = {};
list.forEach(item => {
obj[item.state] = Object.assign({}, item);
});
return obj;
}
Upvotes: 1
Views: 394
Reputation: 311
With reduce its quit easy.
function transform(list) {
return list.reduce((latestState, { state, city, population }) => {
const isNewEntry = !(state in latestState);
if(isNewEntry){
latestState[state] = {
count: 1,
city: [city],
population: population
}
}else{
latestState[state] = {
count: latestState[state].count + 1,
city: [...latestState[state].city, city],
population: latestState[state].population + population
}
}
return latestState;
}, {});
}
So whats going on here.
With reduce we loop over the list and every new loop we receive the latest state, in this example we start with a empty object.
Next, we check if entry needs creation or a update (exists). Based on isNewEntry
we create or update the entry.
https://codesandbox.io/s/amazing-ellis-mh4b6
Upvotes: 2
Reputation: 350137
You could use Object.fromEntries
to create the state/object mapping, and then iterate the original list to aggregate the count, city and population:
function mergeValues(list) {
let obj = Object.fromEntries(list.map(({state}) =>
[state, { count: 0, city: [], population: 0 }]
));
list.forEach(({state, city, population}) => {
obj[state].count++;
obj[state].city.push(city);
obj[state].population += population;
});
return obj;
}
var list = [{ state: 'NJ', city: 'Newark', population: 150 },{ state: 'NJ', city: 'Trenton', population: 200 },{ state: 'NY', city: 'New York City', population: 500 },{ state: 'MI', city: 'Detroit', population: 200 },{ state: 'MI', city: 'Lansing', population: 100 }];
console.log(mergeValues(list));
Upvotes: 1