使用 lodash 展平嵌套对象

问题描述 投票:0回答:4

我正用头撞井,试图用 lodash 做以下事情。我有一个包含更多嵌套对象的对象数组,如下所示:

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

我想把这个数组的每个元素转换成这样的:

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

所以基本上我想“展平”数组的每个元素,以便根据主键和子键确定对象键。我如何使用 lodash 或普通 JS 来完成此任务?

您可以假设只有 1 层嵌套,如示例所示。

javascript lodash
4个回答
11
投票

您可以简单地使用 npm 包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',
    },
    // ...
  ]
*/

如果你想自己实现它,这是我的实现

flat

const flat = (obj, concatenator = '.') => (
  Object.keys(obj).reduce(
    (acc, key) => {
      if (typeof obj[key] !== 'object' || !obj[key]) {
        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));

这些解决方案适用于任何深度。


4
投票

您可以在没有 lodash (或其他库)的情况下通过迭代原始数组中每个项目的键,检查它们的类型,并进一步迭代它们的内部键,构建新键来保存正确的值来完成此操作。

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);

当然,这不一定非常漂亮或灵活(根据您对单层深度的假设)。


0
投票

还有无需 loadash 即可处理嵌套对象的解决方案

function objectToPathsValues(item: any): { [key: string]: any } {

    let newObj = {};
    let path = '';

    flattingNestedObject(item,path, newObj);

    return newObj;

}
function flattingNestedObject(item: any,path: string, output: { [key: string]: any }): void {
    Object.keys(item).forEach(key => {
        const combinedPath = path ? `${path}.${key}` : key;
        if (typeof item[key] === 'object') {

            flattingNestedObject(item[key],combinedPath, output);
        } else {
            output[combinedPath] = item[key];
        }
    });
}

只需致电

objectToPathsValues(yourHugeObjectWithNestedObjectChildren);

唯一的一点是你的对象没有循环嵌套对象。


0
投票

只需使用扁平

import { flatten } from 'flat'

flatten({
    key1: {
        keyA: 'valueI'
    },
    key2: {
        keyB: 'valueII'
    },
    key3: { a: { b: { c: 2 } } }
})

// {
//   'key1.keyA': 'valueI',
//   'key2.keyB': 'valueII',
//   'key3.a.b.c': 2
// }
© www.soinside.com 2019 - 2024. All rights reserved.