I have an array with objects, that can have children, the children have the same structure as the parent, it's just object nesting basically.
I'm wondering how I can flatten the structure of my objects so I have the id's of all the objects, including the nested one's.
For example, This structure
const data = [
{
id: 2,
children: [
{
id: 1,
children: []
}
]
},
{
id: 3,
children: [],
}
]
Should be flattened to this
const data = [2,1,3]
I've tried
Using Array.reduce() and the object spread syntax, but I can't wrap my head around the logic required to do this.
9 Answers 9
const data = [
{
id: 2,
children: [
{
id: 1,
children: []
}
]
},
{
id: 3,
children: [],
}
]
const getIds = (data) => data.map(d => [d.id, ...getIds(d.children)]).flat()
console.log(getIds(data))
2 Comments
This is a job for recursion. Loop over the array and for each element in it, push the id into a new array and repeat for the children.
const data = [{
id: 2,
children: [{
id: 1,
children: []
}]
},
{
id: 3,
children: [],
}
];
console.log(flatten(data));
function flatten(data) {
const result = [];
recursive(data);
return result;
function recursive(data) {
data.forEach(member => {
result.push(member.id);
recursive(member.children);
});
}
}
Comments
You can use JSON.stringify, and for each key of id, push to an array:
const data = [
{
id: 2,
children: [
{
id: 1,
children: []
}
]
},
{
id: 3,
children: [],
}
]
const ids = [];
JSON.stringify(data, (key, val) => {
if (key === 'id') {
ids.push(val);
}
return val;
});
console.log(ids);
You can do some recursive approach.
function flatArr(arr, res) {
// iterate over the array
arr.forEach(o => {
// check id is present then push it into the result array
if ('id' in o) res.push(o.id)
// check children is present and non-empty
// then ecursively call the function
if (o.children && o.children.length) flatArr(o.children, res);
})
// return the result array(optional)
return res;
}
console.log(flatArr(data, []));
const data = [{
id: 2,
children: [{
id: 1,
children: []
}]
},
{
id: 3,
children: [],
}
];
function flatArr(arr, res) {
// iterate over the array
arr.forEach(o => {
// check id is present then push it into the result array
if ('id' in o) res.push(o.id)
// check children is present and non-empty
// then ecursively call the function
if (o.children && o.children.length) flatArr(o.children, res);
})
// return the result array(optional since it's the same array reference you are passing initially)
return res;
}
console.log(flatArr(data, []));
Comments
You can use recursion.Note that is below code reference of arr is passed so we can directly push() ids to it and no need to get return value
const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ]
function getIds(data,arr){
//iterate over array of chilren
for(let child of data){
//add id of each child to arr
arr.push(child.id);
//check if child have children add its 'ids' to same array
if(child.children) getIds(child.children,arr);
}
//return array in end
return arr;
}
console.log(getIds(data,[]))
Comments
I do not like recursions :)
Do note the other Stringify answer - ILST
https://stackoverflow.com/a/55179326/295783
const data=[{id:2,children:[{id:1,children:[]}]},{id:3,children:[],}];
console.log(
JSON.stringify(data)
.match(/(?:"id":)(\d+)/g)
.map(v => +v.replace(/"id":/g, ""))
)
I however wish someone could find me a way to ignore the non-capturing group in one go
2 Comments
Number. Really odd solution +1You could reduce the array of objects by using the actual id and get their children objects.
const
getId = array => array.reduce(
(r, { id, children }) => [...r, id, ...getId(children)],
[]
),
data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [] }],
ids = getId(data);
console.log(ids);
Comments
You can use a recursive approach and iterate for each children and push all the id in an array.
const data = [{ id: 2, children: [{ id: 1, children: [] }] }, { id: 3, children: [], } ],
getId = (data) => data.reduce((r,{id, children}) => r.concat(id, getId(children)),[]);
console.log(getId(data));
Comments
Another version. Not the prettiest but gets the job done:
const data = [
{
id: 2,
children: [
{
id: 1,
children: []
}
]
},
{
id: 3,
children: [],
}
];
let mappedArray = data.map(num => [].concat(num.children.map(child => child.id)).concat(num.id));
mappedArray = [].concat.apply([], mappedArray);
console.log(mappedArray);