问题
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