Home > Mobile >  Reverse Nested Tree with Multiple Top Level Parents & Index
Reverse Nested Tree with Multiple Top Level Parents & Index

Time:11-21

i have the following data structure

[
  {
    id: 1,
    name: 'Top Level Topic 1',
    parentTopic: undefined
  },
  {
    id: 2,
    name: 'Some topic internally',
    parentTopic: 1
  },
  {
    id: 3,
    name: 'Another topic',
    parentTopic: 2
  },
  { id: 4, name: 'Just another topic', parentTopic: 2 },
  {
    id: 5,
    name: 'Another topic',
    parentTopic: 1
  },
  {
    id: 6,
    name: 'Another topic',
    parentTopic: 5
  },
  {
    id: 7,
    name: 'Another topic',
    parentTopic: 5
  },
  { id: 8, name: 'Another topic', parentTopic: 1 },
  {
    id: 9,
    name: 'Another topic',
    parentTopic: 8
  },
  {
    id: 10,
    name: 'Another topic',
    parentTopic: 9
  },
  {
    id: 11,
    name: 'Another topic',
    parentTopic: 10
  },
  {
    id: 12,
    name: 'Another Top Level Topic',
    parentTopic: undefined
  },
  { id: 13, name: 'Another Important Topic', parentTopic: 12 }]

I am trying to convert & construct it in the following manner

[
  {
    id: 1,
    name: 'Top Level Topic 1',
    parentTopic: undefined,
    index: 1,
    children: [
      {
        id: 2,
        name: 'Some topic internally',
        parentTopic: 1,
        index: 1.1,
        children: [
          {
            id: 3,
            name: 'Another topic',
            parentTopic: 2,
            index: 1.1.1,
            children: []
          },
          {
            id: 4,
            name: 'Just another topic',
            parentTopic: 2,
            index: 1.1.2,
            children: []
          },
        ]
      },
      {
        id: 5,
        name: 'Another topic',
        parentTopic: 1,
        index: 1.2,
        children: [
          {
            id: 6,
            name: 'Another topic',
            parentTopic: 5,
            index: 1.2.1,
            children: []
          },
          {
            id: 7,
            name: 'Another topic',
            parentTopic: 5,
            index: 1.2.2,
            children: []
          },
        ]
      },
      {
        id: 8,
        name: 'Another topic',
        parentTopic: 1,
        index: 1.3,
        children: [
            {
              id: 9,
              name: 'Another topic',
              parentTopic: 8,
              index: 1.3.1,
              children: [
                {
                  id: 10,
                  name: 'Another topic',
                  parentTopic: 9,
                  index: 1.3.1.1,
                  children: []
                },
              ]
            },
        ]
      },
    ]
  },
  {
    id: 12,
    name: 'Another Top Level Topic',
    parentTopic: undefined,
    index: 2
    children: [
      {
        id: 13,
        name: 'Another Important Topic',
        parentTopic: 12,
        index: 2.1,
        children: []
      },
    ]
  },
]

My challenge is that I am not sure how to recursively perform this. Also in the output you will notice an index, which could be nice to generate as one iterates or it could just come from the db, meaning my original data structure would already have it.

I would really appreciate if anyone could help me with this :)

Here is my code which works but at the top level its a dictionary instead of being list of dictionaries

    const invertHierarchy = (arr) => {
      const map = {};
      let root;
      for (const ele of arr) {
        map[ele.id] = ele;
        ele.topics = [];
      }
      for (const ele of arr) {
        if (map[ele.parentTopic] != null) map[ele.parentTopic].topics.push(ele);
        else root = ele;
      }
      return root;
    };

CodePudding user response:

const data = [{"id":1,"name":"Top Level Topic 1"},{"id":2,"name":"Some topic internally","parentTopic":1},{"id":3,"name":"Another topic","parentTopic":2},{"id":4,"name":"Just another topic","parentTopic":2},{"id":5,"name":"Another topic","parentTopic":1},{"id":6,"name":"Another topic","parentTopic":5},{"id":7,"name":"Another topic","parentTopic":5},{"id":8,"name":"Another topic","parentTopic":1},{"id":9,"name":"Another topic","parentTopic":8},{"id":10,"name":"Another topic","parentTopic":9},{"id":11,"name":"Another topic","parentTopic":10},{"id":12,"name":"Another Top Level Topic"},{"id":13,"name":"Another Important Topic","parentTopic":12}];

const getPrefix = (prefix, i) => prefix ? `${prefix}.${i 1}` : `${i 1}`

const f = (arr, parentTopic, prefix) =>
  arr.filter(e=>e.parentTopic===parentTopic).map((e,i)=>({
    ...e,
    index: getPrefix(prefix,i),
    children: f(arr, e.id, getPrefix(prefix,i))
}))

console.log(f(data))

CodePudding user response:

You could take another approach by storing all nodes and their parents in an object and take only the array with no parents as result.

By using a single loop, it builds the index as well on the fly.

const
    data = [{ id: 1, name: 'Top Level Topic 1', parentTopic: undefined }, { id: 2, name: 'Some topic internally', parentTopic: 1 }, { id: 3, name: 'Another topic', parentTopic: 2 }, { id: 4, name: 'Just another topic', parentTopic: 2 }, { id: 5, name: 'Another topic', parentTopic: 1 }, { id: 6, name: 'Another topic', parentTopic: 5 }, { id: 7, name: 'Another topic', parentTopic: 5 }, { id: 8, name: 'Another topic', parentTopic: 1 }, { id: 9, name: 'Another topic', parentTopic: 8 }, { id: 10, name: 'Another topic', parentTopic: 9 }, { id: 11, name: 'Another topic', parentTopic: 10 }, { id: 12, name: 'Another Top Level Topic', parentTopic: undefined }, { id: 13, name: 'Another Important Topic', parentTopic: 12 }],
    tree = function(data, root) {
        const t = {};
        data.forEach(o => {
            Object.assign(t[o.id] ??= {}, { ...o });
            ((t[o.parentTopic] ??= {}).children ??= []).push(t[o.id]);
            const index = t[o.parentTopic].index || '';
            t[o.id].index = index   (index && '.')   t[o.parentTopic].children.length;
        });
        return t[root].children;
    }(data, undefined);

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

  • Related