简体   繁体   中英

How to filter an array of objects into a single object and organised by its keys?

i'm trying to filter an array of objects and return a single object, organised by the keys continents , countries and cities and we place those objects in the correct key.

const data = [{
  location: [{
      name: 'Africa',
      type: 'Continent'
    },
    {
      name: 'Angola',
      type: 'Country'
    },
    {
      name: 'Luanda',
      type: 'City'
    }
  ],
  values: []
}, {
  location: [{
      name: 'Europe',
      type: 'Continent'
    },
    {
      name: 'Italy',
      type: 'Country'
    },
    {
      name: 'Rome',
      type: 'City'
    }
  ],
  values: []
}, {
  location: [{
      name: 'Europe',
      type: 'Continent'
    },
    {
      name: 'Spain',
      type: 'Country'
    },
    {
      name: 'Valencia',
      type: 'City'
    }
  ],
  values: []
}]

It should result in:

{

  Africa: {
    countries: {
      Angola: {
        cities: {
          Luanda: {
            values: []
          }
        }
      }
    }
  },

  Europe: {
    countries: {
      Italy: {
        cities: {
          Rome: {
            values: []
          }
        }
      },
      Spain: {
        cities: {
          Valencia: {
            values: []
          }
        }
      }
    }
  }
}

I've tried to filter by its keys but when it comes to placing the objects in the right place (eg by same Continent) I couldn't get it working.

const result = data.reduce((acc, total) => {
  const continentFilter = total.location.find(s => s.type === 'Continent')

  acc[continentFilter.name] = {
    // ...
  }
  return acc
}, {})


console.log(result)
// {
//  Africa: { ... },
//  Europe: { ... }
// }

UPDATE:

  • The type is always 'Continent', 'Country', or 'City'
  • Some Continents/Countries might not have a City
  • The goal is to organize by Continent , then by Country and City

You could take an array for the nested properties which are not given by the location arrays (maybe there could be the key instead of unused type ).

Then iterate the array and create a nested structure. At the end apply the values.

For unsorted location sort it in advance.

 const data = [{ location: [{ name: 'Angola', type: 'Country' }, { name: 'Luanda', type: 'City' }, { name: 'Africa', type: 'Continent' }], values: [] }, { location: [{ name: 'Europe', type: 'Continent' }, { name: 'Italy', type: 'Country' }, { name: 'Rome', type: 'City' }], values: [] }, { location: [{ name: 'Europe',type: 'Continent' }, { name: 'Spain', type: 'Country' }, { name: 'Valencia', type: 'City' }], values: [] }]; levels = ['countries', 'cities'], result = data.reduce((r, { location, values }) => { const order = { Continent: 1, Country: 2, City: 3 }, temp = location.sort((a, b) => order[a.type] - order[b.type]).reduce((o, { name }, i) => { o[name]??= {}; return levels[i]? (o[name][levels[i]]??= {}): o[name]; }, r); (temp.values??= []).push(...values); return r; }, {}); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

Here's a working example. I'm sure it can be improved.

 const data = [{ location: [{ name: 'Africa', type: 'Continent' }, { name: 'Angola', type: 'Country' }, { name: 'Luanda', type: 'City' } ], values: [] }, { location: [{ name: 'Europe', type: 'Continent' }, { name: 'Italy', type: 'Country' }, { name: 'Rome', type: 'City' } ], values: [] }, { location: [{ name: 'Europe', type: 'Continent' }, { name: 'Spain', type: 'Country' }, { name: 'Valencia', type: 'City' } ], values: [] }]; function countryDataToStructuredObject(data){ let countryData = { }; data.map(a => { countryData[a.location.find(x => x.type == 'Continent').name] = {}; countryData[a.location.find(x => x.type == 'Continent').name]['countries'] = {}; countryData[a.location.find(x => x.type == 'Continent').name]['countries'][a.location.find(x => x.type == 'Country').name] = {}; countryData[a.location.find(x => x.type == 'Continent').name]['countries'][a.location.find(x => x.type == 'Country').name]['cities'] = {}; countryData[a.location.find(x => x.type == 'Continent').name]['countries'][a.location.find(x => x.type == 'Country').name]['cities'][a.location.find(x => x.type == 'City').name] = { values: a.values }; }); return countryData; } console.log(countryDataToStructuredObject(data));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM