简体   繁体   中英

Flatten nested objects with lodash

I'm banging my head against a well trying to do the following with lodash. I have an array of objects with more nested objects, which looks like this:

[{
    id: 123,
    name: 'John',
    summary1: {
        count: 3,
        sum: 10,
    },
    summary2: {
        count: 10,
        sum: 20
    },
},
...
]

I want to convert each element of this array into something like this:

[{
    id: 123,
    name: 'John',
    summary1_count: 3,
    summary1_sum: 10
    summary2_count: 10,
    summary2_sum: 20,
},
...
]

SO basically I want to "flatten" each element of the array, in a way such that object keys are determined based on the main and subkeys. How can I accomplish this using lodash or plain JS?

You can assume there's just 1 level of nesting like in the example.

You can simply use the npm package flat .

import flat from 'flat';

const array = [
  {
    a: 'a',
    b: {
      bb: 'bb',
    },
    c: {
      cc1: 'cc1',
      cc: {
        ccc: 'ccc',
        ccd: 'ccd',
      },
    },
  },
  // ...
];

const flattenedArray = array.map(flat);

/*
  flattenedArray === [
    {
      a: 'a',
      b.bb: 'bb',
      c.cc1: 'cc1',
      c.cc.ccc: 'ccc',
      c.cc.ccd: 'ccd',
    },
    // ...
  ]
*/

And if you want to implement it yourself, here's my implementation of flat :

const flat = (obj, concatenator = '.') => (
  Object.keys(obj).reduce(
    (acc, key) => {
      if (typeof obj[key] !== 'object') {
        return {
          ...acc,
          [key]: obj[key],
        };
      }

      const flattenedChild = flat(obj[key], concatenator);

      return {
        ...acc,
        ...Object.keys(flattenedChild).reduce((childAcc, childKey) => ({ ...childAcc, [`${key}${concatenator}${childKey}`]: flattenedChild[childKey] }), {}),
      };
    },
    {},
  )
);

const flattenedArray = array.map(o => flat(o));

Those solutions will work with any depth.

You can do this without lodash (or another library) by iterating over the keys of each item in the original array, checking their type, and further iterating over their internal keys, building new keys to hold the right values.

 const array = [{ id: 123, name: 'John', summary1: { count: 3, sum: 10 }, summary2: { count: 10, sum: 20 } }]; let newArray = array.map(item => { let newObj = {}; Object.keys(item).forEach(key => { if (typeof item[key] === 'object') { Object.keys(item[key]).forEach(innerKey => { newObj[`${key}_${innerKey}`] = item[key][innerKey]; }); } else { newObj[key] = item[key]; } }); return newObj; }); console.log(newArray); 

Granted, this isn't necessarily very pretty or flexible (following your assumption of a single level deep).

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