我有一個如下的源陣列:
var source = [
{
node : 1,
text : "pen",
parent : null
},
{
node : 11,
text : "pencil",
parent : 1
},
{
node : 12,
text : "mango",
parent : 1
},
{
node : 111,
text : "mango",
parent : 11
},
{
node : 112,
text : "banana",
parent : 11
},
{
node : 211,
text : "Cilli",
parent : 12
},
{
node : 1111,
text : "banana",
parent : 111
},
{
node : 2,
text : "Grapes",
parent : null
},
{
node : 21,
text : "Mango",
parent : 2
},
{
node : 3,
text : "banana",
parent : null
},
]
因此,如您所見,節點 1 的父節點為空,因此它是父節點。此外,節點 11 的父節點是 1,因此 11 是節點 1 的子節點,依此類推。我想要一個如下創建的目標陣列:我需要使用下面的陣列來創建一棵樹
var target = [
{
node : 1 ,
children :[
{
node : 11,
children : [
{
node : 111,
children :[
{
node:1111,
children :[]
}]
},
{
node : 112,
children:[]
}
]
},
{
node : 12,
children : []
},
]
},
{
node : 2,
children :[
{
node : 21,
children :[]
}]
},
{
node:3,
children:[]
}
]
我正在嘗試 array.forEach 但這并沒有多大幫助
uj5u.com熱心網友回復:
這可以作業。
var source = [ { node : 1, text : "pen", parent : null }, { node : 11, text : "pencil", parent : 1 }, { node : 12, text : "mango", parent : 1 }, { node : 111, text : "mango", parent : 11 }, { node : 112, text : "banana", parent : 11 }, { node : 211, text : "Cilli", parent : 12 }, { node : 1111, text : "banana", parent : 111 }, { node : 2, text : "Grapes", parent : null }, { node : 21, text : "Mango", parent : 2 }, { node : 3, text : "banana", parent : null }, ];
const result = [];
const map = source.reduce((acc, {node, parent}) => {
acc[node] = {node, children: []};
return acc;
}, {});
source.forEach(({node, parent}) => {
if (!parent) {
result.push(map[node]);
} else {
map[parent]?.children?.push(map[node]);
}
});
console.log(result);
uj5u.com熱心網友回復:
// using an object `childrenFor` to keep track of all `.children` arrays while we fill them.
const target = source.reduce((childrenFor, item) => {
// adding the children array to item
item.children = childrenFor[item.node] ??= [];
// adding the item to the children array for its parent
(childrenFor[item.parent] ??= []).push(item);
//passing the cache through to the next iteration
return childrenFor;
}, {})[null]; // selecting the list for items with `parent: null`
field ??= [] 是否“獲取或創建陣列”。
顯示代碼片段
var source = [{
node: 1,
text: "pen",
parent: null
},
{
node: 11,
text: "pencil",
parent: 1
},
{
node: 12,
text: "mango",
parent: 1
},
{
node: 111,
text: "mango",
parent: 11
},
{
node: 112,
text: "banana",
parent: 11
},
{
node: 211,
text: "Cilli",
parent: 12
},
{
node: 1111,
text: "banana",
parent: 111
},
{
node: 2,
text: "Grapes",
parent: null
},
{
node: 21,
text: "Mango",
parent: 2
},
{
node: 3,
text: "banana",
parent: null
},
];
const target = source.reduce((childrenFor, item) => {
item.children = childrenFor[item.node] ??= [];
(childrenFor[item.parent] ??= []).push(item);
return childrenFor;
}, {})[null];
console.log(target);
.as-console-wrapper{top:0;max-height:100%!important}
uj5u.com熱心網友回復:
我們可以撰寫makeTree一個帶有 3 個引數的泛型函式 -
- 輸入作為節點的平面串列
- 標識每個節點的父節點的函式
- 以您想要的形狀構建樹節點的函式
const source =
[{node:1,text:"pen",parent:null },{node:11,text:"pencil",parent:1},{node:12,text:"mango",parent:1},{node:111,text:"mango",parent:11},{node:112,text:"banana",parent:11},{node:211,text:"Cilli",parent:12},{node:1111,text:"banana",parent:111},{node:2,text:"Grapes",parent:null},{node:21,text:"Mango",parent:2},{node:3,text:"banana",parent:null},]
const result =
makeTree
( source // 1
, (node) => node.parent // 2
, (node, next) => ({ ...node, children: next(node.node) }) // 3
)
makeTree具有適當的通用性,允許它處理任何輸入陣列。我們有一個很好的機會來學習相互遞回 -
many需要很多的投入,并呼吁one每個one構建一個新節點并呼叫many所有子節點
事實證明,這種圓形排列非常適合分支遞回結構,例如所需輸出中的樹 -
function makeTree(input, indexer, maker, root = null) {
const index = makeIndex(input, indexer)
const many = (all = []) => all.map(one) // 1
const one = (single = {}) => maker(single, r => many(index.get(r))) // 2
return many(index.get(root))
}
makeTree由于使用了另一個通用的makeIndex,它使用 aMap進行快速查找,因此即使對于大輸入也非常快 -
function makeIndex(items, indexer) {
const insert = (r, k, v) => r.set(k, (r.get(k) ?? []).concat([ v ]))
return items.reduce((r, i) => insert(r, indexer(i), i), new Map)
}
我們已經完成了實施。讓我們看看result——
console.log(JSON.stringify(result, null, 2))
展開下面的代碼段以在您自己的瀏覽器中驗證結果 -
顯示代碼片段
function makeTree(input, indexer, maker, root = null) {
const index = makeIndex(input, indexer)
const many = (all = []) => all.map(one)
const one = (single = {}) => maker(single, r => many(index.get(r)))
return many(index.get(root))
}
function makeIndex(items, indexer) {
const insert = (r, k, v) => r.set(k, (r.get(k) ?? []).concat([ v ]))
return items.reduce((r, i) => insert(r, indexer(i), i), new Map)
}
const source =
[{node:1,text:"pen",parent:null },{node:11,text:"pencil",parent:1},{node:12,text:"mango",parent:1},{node:111,text:"mango",parent:11},{node:112,text:"banana",parent:11},{node:211,text:"Cilli",parent:12},{node:1111,text:"banana",parent:111},{node:2,text:"Grapes",parent:null},{node:21,text:"Mango",parent:2},{node:3,text:"banana",parent:null},]
const result =
makeTree
( source
, (node) => node.parent
, (node, next) => ({ ...node, children: next(node.node) })
)
console.log(JSON.stringify(result, null, 2))
[
{
"node": 1,
"text": "pen",
"parent": null,
"children": [
{
"node": 11,
"text": "pencil",
"parent": 1,
"children": [
{
"node": 111,
"text": "mango",
"parent": 11,
"children": [
{
"node": 1111,
"text": "banana",
"parent": 111,
"children": []
}
]
},
{
"node": 112,
"text": "banana",
"parent": 11,
"children": []
}
]
},
{
"node": 12,
"text": "mango",
"parent": 1,
"children": [
{
"node": 211,
"text": "Cilli",
"parent": 12,
"children": []
}
]
}
]
},
{
"node": 2,
"text": "Grapes",
"parent": null,
"children": [
{
"node": 21,
"text": "Mango",
"parent": 2,
"children": []
}
]
},
{
"node": 3,
"text": "banana",
"parent": null,
"children": []
}
]
請參閱此相關問答以獲取有關如何抽象makeTree并makeIndex融入其自己模塊的建議。此處解釋的技術將幫助您了解我們以這種方式設計程式的方式和原因的基礎知識。如果您有任何問題,請詢問。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/361810.html
標籤:javascript 数组
