如何从对象数组中获取键和子键?

5

我有下面这个对象数组。

const array = [{
  field1: "val1",
  field2: "val2",
  field3: {
    field1: "val1",
    field2: "val2"
  }
},
{
  field1: "val1",
  field2: "val2",
  field3: {
    field1: "val1"
  }
}]

我需要获得以下输出。
const output = [{
  key: "field1",
  subkeys: []
},
{
  key: "field2",
  subkeys: []
},
{
  key: "field3",
  subkeys: ["field1", "field2"]
}]

我可以使用这个方法获取顶级字段

const keys = array.map(x => Object.keys(x)[0]);

但无法访问内部元素。

请帮忙……谢谢!!!


1
你的对象只有两个层级吗? - Nina Scholz
@DarkKnight:您期望的输出是什么?const output = [[{key: "field1", subkeys: [] }, {key: "field2", subkeys: [] }, {key: "field3", subkeys: ["field1", "field2"] }], [{key: "field1", subkeys: [] }, {key: "field2", subkeys: [] }, {key: "field3", subkeys: ["field1"] }]]这是一个二维数组吗?还是问题中提到的那个? - Dhivya Dandapani
如问题所述,不是一个数组的数组。 - Dark Knight
@DarkKnight:谢谢。但是到目前为止被选中的答案似乎没有返回预期的答案。您还在寻找准确的答案吗? - Dhivya Dandapani
@DarkKnight:你能否提供一个多层嵌套的JSON输入输出示例?我已经发布了一个答案。根据您的要求,我可以进行修改。 - Dhivya Dandapani
4个回答

2
你可以在顶层对一个对象键的数组进行缩减,然后检查该键的值是否为对象——如果是,则获取它的嵌套键;否则留下空的子键数组。

const array = [{
  field1: "val1",
  field2: "val2",
  field3: {
    field1: "val1",
    field2: "val2"
  }
},
{
  field1: "val1",
  field2: "val2",
  field3: {
    field1: "val1"
  }
}]

const result = array.map(item => {
  return Object.keys(item).reduce((acc, rec) => {
    if(typeof item[rec] === 'object') {
      return [...acc, {key: rec, subkeys: Object.keys(item[rec])}] 
    }
    return [...acc, {key: rec, subkeys: []}]
  }, [])
})

console.log(result)


只是一个小问题...它能否适用于未知的级别? - Dark Knight
@DarkKnight 对于未知级别的函数应该使用递归。reduce 应该被写成一个函数,并且在 typeof 新子节点是对象的条件下 - 只需运行递归即可。 - elvira.genkel
请注意reduce ({...spread})反模式 - Moritz Roessler

2

您可以通过查找嵌套对象来进行任何深度的映射。

const
    getKeys = object => Object.keys(object).map(key => ({ 
        key, 
        subkeys: object[key] && typeof object[key] === 'object'
            ? getKeys(object[key])
            : []
    })),
    array = [{ field1: "val1", field2: "val2", field3: { field1: "val1", field2: "val2" } }, { field1: "val1", field2: "val2", field3: { field1: "val1" } }];

console.log(array.map(getKeys));
.as-console-wrapper { max-height: 100% !important; top: 0; }


2

这个解决方案使用了lodash库。我已经提取了变量以便更好的可读性。这个解决方案适用于2级。

const array = [
    {"field1":"val1","field2":"val2","field3":{"field1":"val1","field2":"val2"}},
    {"field1":"val1","field2":"val2","field3":{"field1":"val1","field4":"val1"}}
];

intermediateOutput = array.reduce(
  (accumulator, entry) => _.merge(accumulator, entry),
{});
// intermediateOutput = {"field1":"val1","field2":"val2","field3":{"field1":"val1","field2":"val2","field4":"val1"}}

const finalOutput = _.map(_.keys(intermediateOutput), (key) => {
  const value = intermediateOutput[key];
  return {key, subkeys: _.isObject(value) ? _.keys(value): [] }
})

console.log(finalOutput);
// finalOutput = [{"key":"field1","subkeys":[]},{"key":"field2","subkeys":[]},{"key":"field3","subkeys":["field1","field2","field4"]}]

其实我有一个对象数组 https://lodashfiddle.herokuapp.com/ka6dpidr/ ...。我需要这些键保持不变,但是值为空字符串。 - Dark Knight
@DarkKnight:感谢您提供的lodashfiddle。在fiddle中发布的数组似乎格式不太正确。另外,如果您在lodashfiddle中发布的数组的注释中也提到预期输出,那将会更有帮助。 - Dhivya Dandapani

1
const output = []
for (let [key, value] of Object.entries(array)) {
    const subkeys = Object.keys(value)
    output.push({key, subkeys})
}

类似这样的内容?


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