Search code examples
javascriptangulartypescriptlodash

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


Solution

  • 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, e.g. 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);