遍历嵌套的对象数组
Posted
技术标签:
【中文标题】遍历嵌套的对象数组【英文标题】:Looping through nested array of objects 【发布时间】:2022-01-14 21:30:56 【问题描述】:我有以下对象数组,其中包含嵌套数组。我想遍历这些数组并将所有这些影响信息提取到单独的数组中:
这是我的输入数据的样子:
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
预期输出:
[
"impact": "serious"
,
"impact": "critical"
,
"impact": "serious"
,
"impact": "moderate"
,
"impact": "minor"
,
"impact": "serious"
,
"impact": "serious"
,
"impact": "minor"
,
......
]
我目前正在尝试使用如下的 forEach 循环:
const results = [];
violations.forEach(( nodes, impact ) =>
results.push( impact );
// flattening nodes
nodes.forEach(( any, all, none ) =>
any.forEach((v) => results.push(v));
all.forEach((v) => results.push(v));
none.forEach((v) => results.push(v));
);
);
有没有更好更短的方法来做同样的事情?
【问题讨论】:
有更短的方法来做同样的事情,但以牺牲可读性为代价。我认为您的代码比下面的任何答案都好,因为很容易看到发生了什么,因此更容易维护,并且引入错误的风险很低。这比节省几行代码重要得多。 【参考方案1】:您可以实现如下 sn-p 的结果:
const items =
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
const newItems = items.violations.reduce((acc, impact, nodes)=>
acc.push(impact);
nodes.forEach(item =>
Object.keys(item).forEach(key =>
acc.push(...item[key]);
)
)
return acc
, []);
console.log(newItems);
【讨论】:
【参考方案2】:应该这样做:
const impacts = data.violations.map((impact,nodes) =>
[impact, ...nodes.map((any,all,none) => [...any, ...all, ...none]).flat()]
)
.flat();
const data =
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
;
const impacts = data.violations.map((impact,nodes) =>
[impact, ...nodes.map((any,all,none) => [...any, ...all, ...none]).flat()]
)
.flat();
console.log( impacts );
或者:对你的稍作修改
let results = [];
data.violations.forEach((nodes,impact) =>
results.push(impact);
// flattening nodes
nodes.forEach((any,all,none) =>
results.concat(...[...any, ...all, ...none])
);
);
const data =
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
;
let results = [];
data.violations.forEach(( nodes, impact ) =>
results.push( impact );
// flattening nodes
nodes.forEach(( any, all, none ) =>
results = results.concat(...[...any, ...all, ...none])
);
);
console.log( results );
【讨论】:
值得考虑的好选择。您会向专业编写业务关键型软件的专业人士推荐哪种解决方案? 在这种情况下,任何一个选择都可以,尽管第二个选择可能会快一点。始终考虑易于理解的性能和代码,尤其是后期,因此更易于维护。 是的,我同意,因此,我会选择 OP 的原始解决方案。 此解决方案是否适用于无限级别的数据集?【参考方案3】:这是你的解决方案
let output = []
function recursion(obj, op)
if (typeof obj === 'object')
if (obj.impact)
op.push( impact: obj.impact )
for (var key in obj)
recursion(obj[key], op)
return
recursion(obj, output)
console.log(output)
可运行代码是
let obj =
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
let output = []
function recursion(obj, op)
if (typeof obj === 'object')
if (obj.impact)
op.push( impact: obj.impact )
for (var key in obj)
recursion(obj[key], op)
return
recursion(obj, output)
console.log(output)
【讨论】:
【参考方案4】:我觉得递归将成为你的朋友,优点是无论你如何改变嵌套级别,它都会继续工作。
这将返回一个你正在寻找的数组:
function extractImpactInformation(data)
const results = [];
if (typeof data === 'object')
if (data['impact'])
results.push( 'impact': data['impact'] );
for (const key in data)
results.push(...extractImpactInformation(data[key]));
return results;
const testData =
"violations": [
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "serious"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "minor"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "serious"
,
"impact": "minor"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "serious"
]
]
,
"impact": "serious",
"nodes": [
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
,
"any": [
"impact": "critical"
,
"impact": "critical"
],
"all": [
"impact": "moderate"
],
"none": [
"impact": "moderate"
]
]
]
function extractImpactInformation(data)
const results = [];
if (typeof data === 'object')
if (data['impact'])
results.push( 'impact': data['impact'] );
for (const key in data)
results.push(...extractImpactInformation(data[key]));
return results;
console.log(extractImpactInformation(testData));
【讨论】:
【参考方案5】:您可以像这样创建一个 reducer 函数来对您的影响数据进行分组。
const impactReducer = (acc, impact, nodes) =>
if (impact) acc.push(impact);
nodes?.forEach(node => Object.keys(node).forEach(key => node[key].reduce(impactReducer, acc)));
return acc;
;
const impacts = items.violations.reduce(impactReducer, []);
【讨论】:
以上是关于遍历嵌套的对象数组的主要内容,如果未能解决你的问题,请参考以下文章