简体   繁体   中英

Restructure an array with lodash by leveraging _.map and ._groupBy

I am looking to restructure an array of objects with lodash.

I've been trying to adapt the many examples found online without any luck. It seems I would have to use a combination of _.map and ._groupBy but I can't really wrap my head around this.

Any help is appreciated!

Initial array :

const entries = [
  {
    year: '2019',
    children: [
      { name: 'red', amount: 1, label: 'color' },
      { name: 'yellow', amount: 20, label: 'color' },
      { name: 'green', amount: 12, label: 'color' },
    ],
  },
  {
    year: '2020',
    children: [
      { name: 'red', amount: 1, label: 'color' },
      { name: 'yellow', amount: 3, label: 'color' },
    ],
  },
]

Restructured array :

[
  {
    id: 'red',
    data: [
      { year: '2019', amount: 1 },
      { year: '2020', amount: 1 },
    ],
  },
  {
    id: 'yellow',
    data: [
      { year: '2019', amount: 20 },
      { year: '2020', amount: 3 },
    ],
  },
  {
    id: 'green',
    data: [
      { year: '2019', amount: 12 },
    ],
  },
]

You could chain the whole operations with flatMap , groupBy and mapping.

 const entries = [{ year: '2019', children: [{ name: 'red', amount: 1, label: 'color' }, { name: 'yellow', amount: 20, label: 'color' }, { name: 'green', amount: 12, label: 'color' }] }, { year: '2020', children: [{ name: 'red', amount: 1, label: 'color' }, { name: 'yellow', amount: 3, label: 'color' }] }], result = _(entries).flatMap(({ year, children }) => _.map(children, ({ name: id, amount }) => ({ year, id, amount }))).groupBy('id').map((data, id) => ({ id, data: _.map(data, ({ year, amount }) => ({ year, amount })) })).value(); console.log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

There are probably quite a few different ways of doing this, however, I find the best approach is:

  1. Flatten the children to one array.
  2. Use _.groupBy to create a map of these entries keyed on name.
  3. Use _.entries to get an array of keys and values for the map.
  4. Finally use _.map to transform these entries into our desired output.

 const entries = [ { year: '2019', children: [ { name: 'red', amount: 1, label: 'color' }, { name: 'yellow', amount: 20, label: 'color' }, { name: 'green', amount: 12, label: 'color' }, ], }, { year: '2020', children: [ { name: 'red', amount: 1, label: 'color' }, { name: 'yellow', amount: 3, label: 'color' }, ], }, ] // Step 1 let flattenedChildren = _.flatMap(entries, e => e.children.map(c => { return {...c, year: e.year } })); // Step 2 let entryMap = _.groupBy(flattenedChildren, "name"); // Step 3 let mapEntries = _.entries(entryMap); // Step 4 let result = _.map(mapEntries, ([id, items]) => { return { id, data: items.map(item => _.pick(item, ["amount", "year"]))} }); console.log("Result:", result);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

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