I have an array of objects that contain another array with objects. The nesting is four levels deep. The structure of the array is:
[
{
title: 'Title',
type: 'section',
links: [
{
label: 'Label',
id: 'id_1',
links: [
{
title: 'Title',
type: 'section',
links: [
{
label: 'Label',
id: 'id_2',
links: [
{
label: 'Label',
id: 'id_3',
links: [],
}
]
}
]
},
{
title: 'Other title',
type: 'section',
links: [
{
label: 'Label',
id: 'id_4',
links: [],
}
]
}
]
}
]
}
]
I want to have a flattened array with the id's of the link arrays that contain links (they are parents of submenu's). So the desired outcome is like: ["id_1", "id_2"]
I have tried to get the outcome with this function taken from MDN :
flatDeep(arr, d = 1) {
return d > 0
? arr.reduce((acc, val) =>
acc.concat(Array.isArray(val.links)
? this.flatDeep(val.links, d - 1)
: val.links), [])
: arr.slice();
}
This gives me an empty array.
I think recursive function will simplify. (recursively look for lists
array and push the id
into res).
const data = [ { title: "Title", type: "section", links: [ { label: "Label", id: "id_1", links: [ { title: "Title", type: "section", links: [ { label: "Label", id: "id_2", links: [ { label: "Label", id: "id_3", links: [] } ] } ] }, { title: "Other title", type: "section", links: [ { label: "Label", id: "id_4", links: [] } ] } ] } ] } ]; const res = []; const ids = data => { data.forEach(item => { if ("id" in item) { res.push(item.id); } if (item.links) { ids(item.links); } }); }; ids(data); console.log(res);
You could get a flat array with a recursion and a check for id
for missing property.
const getId = ({ id, links }) => [ ...(id === undefined ? [] : [id]), ...links.flatMap(getId) ], data = [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_1', links: [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_2', links: [{ label: 'Label', id: 'id_3', links: [] }] }] }, { title: 'Other title', type: 'section', links: [{ label: 'Label', id: 'id_4', links: [] }] }] }] }], result = data.flatMap(getId); console.log(result);
var array = JSON.parse('[{"title":"Title","type":"section","links":[{"label":"Label","id":"id_1","links":[{"title":"Title","type":"section","links":[{"label":"Label","id":"id_2","links":[{"label":"Label","id":"id_3","links":[]}]}]},{"title":"Other title","type":"section","links":[{"label":"Label","id":"id_4","links":[]}]}]}]}]'); arr = []; while(array.length != 0) { var ob1 = array.splice(0,1)[0]; for(var ob2 of ob1.links) { if (ob2.links.length !== 0) { arr.push(ob2.id); array = array.concat(ob2.links); } } } console.log(arr);
Here's the output as you requested:
[
"id_1",
"id_2"
]
Use Array.flatMap()
. Destructure each object and use an empty array as default for missing id
values. Concat the id
and the result of flattening the links recursively.
const flattenIds = arr => arr.flatMap(({ id = [], links }) => [].concat(id, flattenIds(links)) ); const data = [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_1', links: [{ title: 'Title', type: 'section', links: [{ label: 'Label', id: 'id_2', links: [{ label: 'Label', id: 'id_3', links: [] }] }] }, { title: 'Other title', type: 'section', links: [{ label: 'Label', id: 'id_4', links: [] }] }] }] }]; const result = flattenIds(data); console.log(result);
Here is a non-recursive version.
const data = [{title:'Title',type:'section',links:[{label:'Label',id:'id_1',links:[{title:'Title',type:'section',links:[{label:'Label',id:'id_2',links:[{label:'Label',id:'id_3',links:[]}]}]},{title:'Other title',type:'section',links:[{label:'Label',id:'id_4',links:[]}]}]}]}]; const stack = data.slice(); const result = []; let obj; while (obj = stack.shift()) { if ("id" in obj && obj.links.length > 0) result.push(obj.id); stack.push(...obj.links); } console.log(result);
This uses breath first, but can easily be changed into depth first. You'll only have to change the stack.push
call into stack.unshift
.
For a more detailed explanation about the two, check out Breadth First Vs Depth First .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.