Home > Net >  Transforming a source flat JavaScript array in a nested array
Transforming a source flat JavaScript array in a nested array

Time:11-21

I have a source array as below :

 var source = [
     {
        node : 1, 
        text : "pen",
        parent : null 
     },
     {
        node : 11, 
        text : "pencil",
        parent : 1
     },
     {
         node : 12, 
         text : "mango",
         parent : 1
     },
     {
          node : 111, 
          text : "mango",
          parent : 11
     },
     {
            node : 112, 
           text : "banana",
           parent : 11
     },
      {
            node : 211, 
            text : "Cilli",
            parent : 12
     },
     {
           node : 1111, 
           text : "banana",
           parent : 111
      },
     {
           node : 2, 
           text : "Grapes",
           parent : null
     },
     {
          node : 21, 
           text : "Mango",
          parent : 2
    },
    {
         node : 3, 
        text : "banana",
        parent : null
    },

   ]

So as you see the parent of node 1 is null, hence it is the parent node. Also, the parent of node 11 is 1, hence 11 is children of node 1 and so on. I want a target array created like below : I need to use below array to create a tree

     var target = [

{
  node : 1 ,
  children :[
    {
      node : 11,
      children : [
          {
              node : 111,
                children :[
                      {
                              node:1111,
                             children :[]
                     }]
         },
        {
          node : 112,
          children:[]
        }

      ]
    },
     {
      node : 12,
      children : []
    },

  ]
},
{
  node : 2,
  children :[
  {
    node : 21,
    children :[]
  }]
},
{
  node:3,
  children:[]
}


]

I am trying array.forEach but that is not helping much

CodePudding user response:

This could work.

var source = [ { node : 1, text : "pen", parent : null }, { node : 11, text : "pencil", parent : 1 }, { node : 12, text : "mango", parent : 1 }, { node : 111, text : "mango", parent : 11 }, { node : 112, text : "banana", parent : 11 }, { node : 211, text : "Cilli", parent : 12 }, { node : 1111, text : "banana", parent : 111 }, { node : 2, text : "Grapes", parent : null }, { node : 21, text : "Mango", parent : 2 }, { node : 3, text : "banana", parent : null }, ];

const result = [];
const map = source.reduce((acc, {node, parent}) => {
  acc[node] = {node, children: []};
  return acc;
}, {});
source.forEach(({node, parent}) => {
  if (!parent) {
    result.push(map[node]);
  } else {
    map[parent]?.children?.push(map[node]);
  }
});

console.log(result);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

// using an object `childrenFor` to keep track of all `.children` arrays while we fill them.
const target = source.reduce((childrenFor, item) => {
  // adding the children array to item
  item.children = childrenFor[item.node] ??= [];

  // adding the item to the children array for its parent
  (childrenFor[item.parent] ??= []).push(item);

  //passing the cache through to the next iteration
  return childrenFor;
}, {})[null]; // selecting the list for items with `parent: null`

field ??= [] does "get or create array".

Show code snippet

var source = [{
    node: 1,
    text: "pen",
    parent: null
  },
  {
    node: 11,
    text: "pencil",
    parent: 1
  },
  {
    node: 12,
    text: "mango",
    parent: 1
  },
  {
    node: 111,
    text: "mango",
    parent: 11
  },
  {
    node: 112,
    text: "banana",
    parent: 11
  },
  {
    node: 211,
    text: "Cilli",
    parent: 12
  },
  {
    node: 1111,
    text: "banana",
    parent: 111
  },
  {
    node: 2,
    text: "Grapes",
    parent: null
  },
  {
    node: 21,
    text: "Mango",
    parent: 2
  },
  {
    node: 3,
    text: "banana",
    parent: null
  },
];

const target = source.reduce((childrenFor, item) => {
  item.children = childrenFor[item.node] ??= [];
  (childrenFor[item.parent] ??= []).push(item);
  
  return childrenFor;
}, {})[null];

console.log(target);
.as-console-wrapper{top:0;max-height:100%!important}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related