2

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.

asked Mar 15, 2019 at 9:23
0

9 Answers 9

5

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))

answered Mar 15, 2019 at 9:29
Sign up to request clarification or add additional context in comments.

2 Comments

This is elegant
I've accepted this answer, like the one-line! Thanks
3

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);
 });
 }
}

answered Mar 15, 2019 at 9:27

Comments

1

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);

answered Mar 15, 2019 at 9:26

2 Comments

Ohhh - Cool. I had no idea stringify took parameters. I also used stringify and then a regex
Strangely enough this does not recurse: JSON.stringify(data,["id"])
1

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, []));

answered Mar 15, 2019 at 9:27

Comments

1

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,[]))

answered Mar 15, 2019 at 9:30

Comments

1

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

answered Mar 15, 2019 at 9:41

2 Comments

Convert each value to Number. Really odd solution +1
@MaheerAli Done ;)
1

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);

mplungjan
180k29 gold badges183 silver badges246 bronze badges
answered Mar 15, 2019 at 9:29

Comments

0

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));

answered Mar 15, 2019 at 9:29

Comments

0

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);

answered Mar 15, 2019 at 10:03

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.