-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

3
  • 4
    Show us what you have tried and where you are running into problems. SO isn't a free code writing service Commented Jul 18, 2020 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); } Commented Jul 18, 2020 at 11:33
  • 1
    Edit the question to include that formatted code along with a more detailed explanation of what is giving you problems Commented Jul 18, 2020 at 11:41

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.