简体   繁体   中英

Flatten an array with nested objects

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.

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

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

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

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

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

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

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

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

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM