使用lodash扁平化嵌套对象

9

我正在尝试使用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级嵌套。

3个回答

10

您可以简单地使用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);

诚然,这并不是非常美观或灵活的(按照您假设的单层深度)。


由于typeof null仍然是object,您可能还想将其添加到条件中,以避免错误。 - keikai

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

你的对象唯一的备注是它没有循环嵌套对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接