Convert flat list array to tree view array based on node number in Javascript

扶醉桌前 提交于 2021-02-07 11:12:30

问题


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


回答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.



来源:https://stackoverflow.com/questions/62967881/convert-flat-list-array-to-tree-view-array-based-on-node-number-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!