Home > Mobile >  Javascript: How to create nested from a linear array based on parent ID
Javascript: How to create nested from a linear array based on parent ID

Time:09-27

I have an array of categories as:

var categories = [
    { 
      name: 'Books', 
      slug: 'books',
      parent_name: null,
    },
    { 
      name: 'Fiction', 
      slug: 'books/fiction',
      parent_name: 'Books'
    },
    { 
      name: 'Romance fiction', 
      slug: 'books/fiction/romance',
      parent_name: 'Fiction'
    },
    { 
      name: 'Bags', 
      slug: 'bags',
      parent_name: null
    }
];

I want to make this array into nested array/object so I can render them in dropdowns menu (upto two levels of dropdowns). But do not have any idea how to do it.

Something like this:

var nestedCatefories = [
   {
      name: 'Books',
      slug: 'books',
      parent_name: null,
      children: [
         {
           name: 'Fiction',
           slug: 'books/fiction',
           parent_name: 'books',
           children: [
              {
                 name: 'Romance',
                 slug: 'books/fiction/romance',
                 parent_name: 'Fiction'
              }
           ]
         }
      ]
   },
   { 
      name: 'Bags', 
      slug: 'bags',
      parent_name: null
    }
];

How do I change this linear array to nested array?

CodePudding user response:

Have you tried using a simple Array.map()? Something like this:

var nestedArr = linearArr.map(obj=>obj.children= [{obj},{obj}])

CodePudding user response:

Reduce the array to a Map, with a predefined root array. For each new item, add it to the Map using it's name as the key. Then get / initialize it's parent's children array, or use root for items without parents. Add the item to it's parent. At the end get the root that hold the entire tree:

const categories = [{"name":"Books","slug":"books","parent_name":null},{"name":"Fiction","slug":"books/fiction","parent_name":"Books"},{"name":"Romance fiction","slug":"books/fiction/romance","parent_name":"Fiction"},{"name":"Bags","slug":"bags","parent_name":null}];

const result = categories.reduce((acc, item) => { 
  acc.set(item.name, item)
  
  const parent = item.parent_name === null 
    ? acc.get('root')
    : (acc.get(item.parent_name).children ??= [])
  
  parent.push(item)

  return acc
}, new Map([['root', []]])).get('root')

console.log(result)

  • Related