简体   繁体   中英

Transform array of objects to a different array of objects - Javascript/Angular

I have an array of object that looks like this. I made it look that way using .groupBy with lodash.

States.ts

STATES: Object[] = [
  {
    USA: [
      {
        name: 'Alabama',
        abbreviation: 'AL',
        country: 'USA'
      },
      {
        name: 'Alaska',
        abbreviation: 'AK',
        country: 'USA'
      }
    ]
  },
  {
    Canada: [
      {
        name: 'Alberta',
        abbreviation: 'ALB',
        country: 'Canada'
      }
    ]
  }
];

I need it to look like this:

    stateList:StateDropdownItem[] =[ 
    {
       label: 'USA', 
       items: [
               {label: 'AL', value: 'Alabama'},
               {label: 'AK', value: 'Alaska'},
       ]
    },
    .
    .
   ]

I have tried the code below, but it doesn't work. When I print it to the console appears undefiened even if I try to put an element without the forloop I get the following error Cannot read property 'push' of undefined

TS

dropdownOfStates: StateDropdownItem[];
.
.
dropdownBuilder() {
    const STATES_BY_COUNTRY = this.getStatesByCountry();
    let tempItem;
    for (let i = 0; i < STATES_BY_COUNTRY.length; i++) {
      tempItem = STATES_BY_COUNTRY[i];
      this.dropdownOfStates.push(
        new StateDropdownItem('KEY COUNTRY VALUE HERE', [
          tempItem.abbreviation,
          tempItem.name
        ])
      );
    }
  }

Console.log after printing the result of using .groupBy with lodash groupby objects by country

You can use the map function of arrays to transform their structure.

The code below should transform it into the structure you want. You can click "Run code snippet" to see the output

 let states = [ { USA: [ { name: 'Alabama', abbreviation: 'AL', country: 'USA' }, { name: 'Alaska', abbreviation: 'AK', country: 'USA' } ] }, { Canada: [ { name: 'Alberta', abbreviation: 'ALB', country: 'Canada' } ] } ]; // Use the code below to transform let res = states.map((val) => { let country = Object.keys(val)[0]; // Get the name of the country, eg USA return { // Return the new object structure label: country, items: val[country].map((item) => ({label: item.abbreviation, value: item.name})) } }); // Log the value console.log(res); 

Here is somewhat more concise method of doing this with ES6 and reduce , Object.keys and map :

 var data = [ { USA: [ { name: 'Alabama', abbreviation: 'AL', country: 'USA' }, { name: 'Alaska', abbreviation: 'AK', country: 'USA' } ] }, { Canada: [ { name: 'Alberta', abbreviation: 'ALB', country: 'Canada' } ] } ]; const result = data.reduce((r,c) => Object.keys(c).map(x => r.push({ label: x, items: c[x].map(y => ({label: y.abbreviation, value: y.name }))})) && r, []) console.log(result) 

This is the expanded variant:

 var data = [ { USA: [ { name: 'Alabama', abbreviation: 'AL', country: 'USA' }, { name: 'Alaska', abbreviation: 'AK', country: 'USA' } ] }, { Canada: [ { name: 'Alberta', abbreviation: 'ALB', country: 'Canada' } ] } ]; const result = data.reduce((r,c) => { Object.keys(c).map(x => { r.push({ label: x, items: c[x].map(y => ({label: y.abbreviation, value: y.name }))})}) return r}, []) console.log(result) 

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