-1

I want to convert flat list array to tree view array based on node number in Javascript. Node number represent child array element. e.g. nodenumber 1.1 represent the children of element "A" and nodenumber 1.1.1 represent the children of element "B" and so on.

input

[
  {
    "name": "A",
    "nodeNumber": "1"
  },
  {
    "name": "B",
    "nodeNumber": "1.1"
  },
  {
    "name": "C",
    "nodeNumber": "1.1.1"
  },
  {
    "name": "D",
    "nodeNumber": "1.2"
  },
  {
    "name": "E",
    "nodeNumber": "1.2.1"
  },
  {
    "name": "F",
    "nodeNumber": "1.2.2"
  }
]

expected output

{
    "name": "A",
    "nodeNumber": "1",
    "children" :[
      {
        "name": "B",
        "nodeNumber": "1.1",
        "children" :[
          {
            "name": "C",
            "nodeNumber": "1.1.1"
          }
        ]
      },
      {
        "name": "D",
        "nodeNumber": "1.2",
        "children" :[
          {
            "name": "E",
            "nodeNumber": "1.2.1"
          },
          {
            "name": "F",
            "nodeNumber": "1.2.2"
          }
        ]
      }
    ]
  }

There is no hierarchy limit.

I have tried to make unique as key for each element and tried to go next step but I got stuck there:

var res = [];
var flatList = [];
input.forEach(loopContent);
function loopContent(item,index,arr) {
    let node = item.nodeNumber.split('.').join('_');
    item['flat_id'] = node;
    res[node] = item; flatList.push(node);
} 

Please help me

Raju
  • 160
  • 2
  • 10
  • 4
    Show us what you have tried and where you are running into problems. SO isn't a free code writing service – charlietfl Jul 18 '20 at 11:20
  • @charlietfl i have tried to make unique as key for each element and tried to go next step but i got stuck there var res = []; var flatList = []; input.forEach(loopContent); function loopContent(item,index,arr) { let node = item.nodeNumber.split('.').join('_'); item['flat_id'] = node; res[node] = item; flatList.push(node); } – Raju Jul 18 '20 at 11:33
  • 1
    Edit the question to include that formatted code along with a more detailed explanation of what is giving you problems – charlietfl Jul 18 '20 at 11:41

1 Answers1

1

A great opportunity to learn about reusable modules and mutual recursion. This solution in this answer solves your specific problem without any modification of the modules written in another answer.

Before we get started, we must first supply a parent function that is unique to your problem.

const parent = (str = "") =>
{ const pos = str.lastIndexOf(".")
  return pos === -1
    ? null
    : str.substr(0, pos)
}

parent("1.2.2")  // => "1.2"
parent("1.2")    // => "1"
parent("1")      //  => null

Now let's build our tree -

// Main.js
import { tree } from './Tree'

const input =
  [ { name: "A", nodeNumber: "1" }, { name: "B", nodeNumber: "1.1" }, { name: "C", nodeNumber: "1.1.1" }, { name: "D", nodeNumber: "1.2" }, { name: "E", nodeNumber: "1.2.1" }, { name: "F", nodeNumber: "1.2.2" } ]

const result =
  tree
    ( input                           // <- array of nodes
    , node => parent(node.nodeNumber) // <- foreign key
    , (node, children) =>             // <- node reconstructor function
        ({ ...node, children: children(node.nodeNumber) }) // <- primary key
    )

console.log(JSON.stringify(result, null, 2))

Output -

[
  {
    "name": "A",
    "nodeNumber": "1",
    "children": [
      {
        "name": "B",
        "nodeNumber": "1.1",
        "children": [
          {
            "name": "C",
            "nodeNumber": "1.1.1",
            "children": []
          }
        ]
      },
      {
        "name": "D",
        "nodeNumber": "1.2",
        "children": [
          {
            "name": "E",
            "nodeNumber": "1.2.1",
            "children": []
          },
          {
            "name": "F",
            "nodeNumber": "1.2.2",
            "children": []
          }
        ]
      }
    ]
  }
]

And that's it. To make this post complete, I will include a copy of the Tree module -

// Tree.js
import { index } from './Index'

const empty =
  {}

function tree (all, indexer, maker, root = null)
{ const cache =
    index(all, indexer)

  const many = (all = []) =>
    all.map(x => one(x))
                             // zero knowledge of forum object shape
  const one = (single) =>
    maker(single, next => many(cache.get(next)))

  return many(cache.get(root))
}

export { empty, tree } // <-- public interface

And the Index module dependency -

// Index.js
const empty = _ =>
  new Map

const update = (r, k, t) =>
  r.set(k, t(r.get(k)))

const append = (r, k, v) =>
  update(r, k, (all = []) => [...all, v])

const index = (all = [], indexer) =>
  all.reduce
      ( (r, v) => append(r, indexer(v), v) // zero knowledge of v shape
      , empty()
      )

export { empty, index, append } // <-- public interface

For additional insight, I encourage you to read the original Q&A.

Mulan
  • 129,518
  • 31
  • 228
  • 259