Home > OS >  Return children tree from array
Return children tree from array

Time:09-01

I have an array of regions the highest region has key: 10 and parent_id: null and I want to restructure this array to return a tree.

Regions tree should look like if the input is [10]

  • Egypt
  • Zone 1
    • Tagamo3
    • Giza
    • Helwan
    • Fayoum
  • Zone 2
    • Gesr ElSuis
      • test
    • Delta
    • Mohandeseen
    • Down Town

Array:

[
            {
                "key": 1,
                "title": "Zone 1",
                "parent_id": 10
            },
            {
                "key": 2,
                "title": "Zone 2",
                "parent_id": 10
            },
            {
                "key": 3,
                "title": "Tagamo3",
                "parent_id": 1
            },
            {
                "key": 4,
                "title": "Gesr ElSuis",
                "parent_id": 2
            },
            {
                "key": 5,
                "title": "Delta",
                "parent_id": 2
            },
            {
                "key": 6,
                "title": "Mohandeseen",
                "parent_id": 2
            },
            {
                "key": 7,
                "title": "Giza",
                "parent_id": 1
            },
            {
                "key": 8,
                "title": "Helwan",
                "parent_id": 1
            },
            {
                "key": 9,
                "title": "Down Town",
                "parent_id": 2
            },
            {
                "key": 10,
                "title": "Egypt",
                "parent_id": null
            },
            {
                "key": 11,
                "title": "Fayoum",
                "parent_id": 1
            },
            {
                "key": 12,
                "title": "test",
                "parent_id": 4
            }
        ]

The output I want to achieve if input is [10]:

[
  {
    "key": 10,
    "title": "Egypt",
    "parent_id": null,
    "children": [
      {
        "key": 1,
        "title": "Zone 1",
        "parent_id": 10,
        "children": [
          {
            "key": 3,
            "title": "Tagamo3",
            "parent_id": 1,
            "children": []
          },
          {
            "key": 7,
            "title": "Giza",
            "parent_id": 1,
            "children": []
          },
          {
            "key": 8,
            "title": "Helwan",
            "parent_id": 1,
            "children": []
          },
          {
            "key": 11,
            "title": "Fayoum",
            "parent_id": 1,
            "children": []
          }
        ]
      },
      {
        "key": 2,
        "title": "Zone 2",
        "parent_id": 10,
        "children": [
          {
            "key": 4,
            "title": "Gesr ElSuis",
            "parent_id": 2,
            "children": [
              {
                "key": 12,
                "title": "test",
                "parent_id": 4,
                "children": []
              }
            ]
          },
          {
            "key": 5,
            "title": "Delta",
            "parent_id": 2,
            "children": []
          },
          {
            "key": 6,
            "title": "Mohandeseen",
            "parent_id": 2,
            "children": []
          },
          {
            "key": 9,
            "title": "Down Town",
            "parent_id": 2,
            "children": []
          }
        ]
      }
    ]
  }
]

Regions tree should look like if the input is [1,2]

  • Zone 1
    • Tagamo3
    • Giza
    • Helwan
    • Fayoum
  • Zone 2
    • Gesr ElSuis
      • test
    • Delta
    • Mohandeseen
    • Down Town

Regions tree should look like if the input is [1]

  • Zone 1
    • Tagamo3
    • Giza
    • Helwan
    • Fayoum

CodePudding user response:

May not be the most optimized, but I gave it a try:

const arr = [{key:1,title:"Zone 1",parent_id:10},{key:2,title:"Zone 2",parent_id:10},{key:3,title:"Tagamo3",parent_id:1},{key:4,title:"Gesr ElSuis",parent_id:2},{key:5,title:"Delta",parent_id:2},{key:6,title:"Mohandeseen",parent_id:2},{key:7,title:"Giza",parent_id:1},{key:8,title:"Helwan",parent_id:1},{key:9,title:"Down Town",parent_id:2},{key:10,title:"Egypt",parent_id:null},{key:11,title:"Fayoum",parent_id:1},{key:12,title:"test",parent_id:4}];

const buildTree = key => arr.filter(x => x.parent_id === key)
                            .map(x => ({ ...x, children: buildTree(x.key) }));
 
console.log(buildTree(null));

To build multiple trees, this could work:

const arr = [{key:1,title:"Zone 1",parent_id:10},{key:2,title:"Zone 2",parent_id:10},{key:3,title:"Tagamo3",parent_id:1},{key:4,title:"Gesr ElSuis",parent_id:2},{key:5,title:"Delta",parent_id:2},{key:6,title:"Mohandeseen",parent_id:2},{key:7,title:"Giza",parent_id:1},{key:8,title:"Helwan",parent_id:1},{key:9,title:"Down Town",parent_id:2},{key:10,title:"Egypt",parent_id:null},{key:11,title:"Fayoum",parent_id:1},{key:12,title:"test",parent_id:4}];

const buildNode = x => ({...x, children: buildTree(x.key)});

const buildTree = key => arr.filter(x => x.parent_id === key)
                            .map(buildNode);

const buildTrees = keys => arr.filter(x => keys.includes(x.key))
                              .map(buildNode);
 
console.log(buildTrees([1, 2]));

CodePudding user response:

based on jcalz snippet, but requires only a single pass over the input array.

const arr = [{key:1,title:"Zone 1",parent_id:10},{key:2,title:"Zone 2",parent_id:10},{key:3,title:"Tagamo3",parent_id:1},{key:4,title:"Gesr ElSuis",parent_id:2},{key:5,title:"Delta",parent_id:2},{key:6,title:"Mohandeseen",parent_id:2},{key:7,title:"Giza",parent_id:1},{key:8,title:"Helwan",parent_id:1},{key:9,title:"Down Town",parent_id:2},{key:10,title:"Egypt",parent_id:null},{key:11,title:"Fayoum",parent_id:1},{key:12,title:"test",parent_id:4}];


/*const lookup: Record<number|"roots", Tree[]> = { roots: [] };*/
const lookup = { roots: [] };

for (const item of arr) {
  // get or create the "children" array for my parent.
  // parent may not be known yet, but I'm already collecting its children, my siblings.
  const siblings = lookup[item.parent_id ?? "roots"] ??= [];
  
  // add myself to that children array.
  siblings.push({
    ...item,
    // get or create my children array.
    children: lookup[item.key] ??= []
  });
}

// it's up to you to handle `lookup.roots.length !== 1`

console.log(lookup.roots);
.as-console-wrapper{top:0;max-height:100%!important}

  • Related