Reputation: 9201
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]
Using Array.reduce() and the object spread syntax, but I can't wrap my head around the logic required to do this.
Upvotes: 2
Views: 1783
Reputation: 386578
You 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);
Upvotes: 1
Reputation: 3568
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);
Upvotes: 0
Reputation: 177940
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
Upvotes: 1
Reputation: 36574
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,[]))
Upvotes: 1
Reputation: 1780
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))
Upvotes: 5
Reputation: 22534
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));
Upvotes: 0
Reputation: 115222
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, []));
Upvotes: 1
Reputation: 943569
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);
});
}
}
Upvotes: 3
Reputation: 4097
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);
Upvotes: 1