Home > Back-end >  Looping through nested array of objects
Looping through nested array of objects

Time:12-10

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;
}
  • Related