how can i construct a new array from a large API by deleting some elements and adding values

Viewed 61

This is the fake data that I've made for testing:

const data =[

    {
        country: 'US',
        city: 'NY',
        population: 1000
    },
    {
        country: 'CA',
        city: 'TOR',
        population: 1000
    },
    {
        country: 'US',
        city: 'LA',
        population: 1000
    },
    {
        country: 'CH',
        city: 'BEI',
        population: 1000
    },
    {
        country: 'CA',
        city: 'VAN',
        population: 1000
    },
    {
        country: 'CH',
        city: 'SHANG',
        population: 1000
    },
]

Let's just pretend that we're working with an API with 100+ countries and many more cities. How do I make a new array out of this array that looks like this:

const finalData = [
    {
        country: 'US',
        population: 2000
    },
    {
        country: 'CA',
        population: 2000
    },
    {
        country: 'CH',
        population: 2000
    },
]

So basically grouping them based on their countries and adding the population from cities with the same country.

3 Answers

You can build a Map using .reduce(), where the map is keyed by the country property. If you encounter a country which is already in the map, you can add to its value storing a summed population count. If the country doesn't exist in the map, you can add the current population as the value with the new country as the key. You can then use Array.from() to convert the Map to an array, where you can provide a mapping function to map the entries to objects:

const data = [ { country: 'US', city: 'NY', population: 1000 }, { country: 'CA', city: 'TOR', population: 1000 }, { country: 'US', city: 'LA', population: 1000 }, { country: 'CH', city: 'BEI', population: 1000 }, { country: 'CA', city: 'VAN', population: 1000 }, { country: 'CH', city: 'SHANG', population: 1000 }, ];

const res = Array.from(data.reduce(
  (m, {country:c, population:p}) => m.set(c, (m.get(c) || 0) + p), new Map
), ([country, population]) => ({country, population}));

console.log(res);

If your goal is to remove the city key and keep all other keys (rather than just keep the country and population keys only), then you can use the following, which will remove the city key, but keep all other keys:

const data = [ { country: 'US', city: 'NY', population: 1000 }, { country: 'CA', city: 'TOR', population: 1000 }, { country: 'US', city: 'LA', population: 1000 }, { country: 'CH', city: 'BEI', population: 1000 }, { country: 'CA', city: 'VAN', population: 1000 }, { country: 'CH', city: 'SHANG', population: 1000}, ];

const res = Array.from(data.reduce((m, {country, city, population, ...r}) => {
  const curr = m.get(country) || {country, population: 0, ...r};
  return m.set(country, {...curr, population: curr.population + population, ...r});
}, new Map).values());

console.log(res);

Use Array#reduce.

let finalData = data.reduce((acc,curr)=>{
     let obj = acc.find(({country})=>country===curr.country);
     if(obj){
         obj.population += curr.population;
     } else {
         acc.push({country:curr.country,population:curr.population});
     }
     return acc;
}, []);

An approach using find method of an array

const data =[

    {
        country: 'US',
        city: 'NY',
        population: 1000
    },
    {
        country: 'CA',
        city: 'TOR',
        population: 1000
    },
    {
        country: 'US',
        city: 'LA',
        population: 1000
    },
    {
        country: 'CH',
        city: 'BEI',
        population: 1000
    },
    {
        country: 'CA',
        city: 'VAN',
        population: 1000
    },
    {
        country: 'CH',
        city: 'SHANG',
        population: 1000
    },
]


var finalArray=[];
data.forEach(obj => {
    
    let temp = finalArray.find( ob => ob['country'] === obj.country );
if(temp!==undefined){
    temp.population +=obj.population;
} else {
  finalArray.push({country:obj.country,population:obj.population})
}

});

console.log(finalArray)

Related