I have following array of objects with nested arrays in it. I wanted to traverse through those arrays and extract all those impact information to separate array:
this is how my input data looks like:
{
"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"
}]
}
]
}
]
}
expected output:
[
{
"impact": "serious"
},
{
"impact": "critical"
},
{
"impact": "serious"
},
{
"impact": "moderate"
},
{
"impact": "minor"
},
{
"impact": "serious"
},
{
"impact": "serious"
},
{
"impact": "minor"
},
......
]
I'm currently trying with forEach loop like below:
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));
});
});
is there any better and shorter way to do the same?
CodePudding user response:
You can achieve your result like below snippet:
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);
CodePudding user response:
here is your solution
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)
Runnable code is
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)
CodePudding user response:
This should do it:
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 );
OR: A slight modification to yours
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.concat(...[...any, ...all, ...none])
);
});
console.log( results );
CodePudding user response:
I feel like recursion is going to be your friend on this one, the advantage being that it will continue to work no matter how much you change your levels of nesting.
This will return an array like what you are looking for:
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;
}