我有這樣的資料:
[
{
id: "1",
parent: null
},
{
id: "2",
parent: null
},
{
id: "3",
parent: "1"
},
{
id: "4",
parent: "3"
},
]
我想將它轉換為具有特定最大深度的樹。有幾種方法可以將陣列轉換為樹,例如這個包,但問題是它們一路走低并創建一個深度嵌套的樹:
[
{
data: { id: "1", parent: null },
children: [
{
data: { id: "3", parent: "1" }
children: [
{
id: "4", parent: "3"
}
]
}
]
},
{
data: { id: "2", parent: null }
}
]
我不希望樹的深度超過特定數量,比如說 1:
[
{
data: { id: "1", parent: null },
children: [
{
data: { id: "3", parent: "1" }
},
{
data: { id: "4", parent: "3" }
}
]
},
{
data: { id: "2", parent: null }
}
]
一種方法是首先創建深度嵌套的物件,然后將我不想嵌套的部分展平,但這可能會改變專案的順序 效率低下。我自己嘗試過幾次創建演算法,但我通常不擅長這些型別的東西。我會很感激一些幫助。想法,例如,任何東西都可能有用。
uj5u.com熱心網友回復:
這是一個解決方案,它使用一個小遞回生成器根據指定的深度獲取所需的節點祖先:
const treeify = (nodes, depth) => {
const index = Object.fromEntries(
nodes.map(node => [node.id, { ...node }])
);
const ancestry = function*(id) {
if (id) {
yield id;
yield* ancestry(index[id].parent);
}
}
nodes.forEach(node => {
const [ancestor] = [...ancestry(node.parent)].slice(-depth);
if (ancestor) {
index[ancestor].children = index[ancestor].children || [];
index[ancestor].children.push(index[node.id]);
}
});
return Object.values(index).filter(node => !node.parent);
}
const data = [
{ id: "1", parent: null }, { id: "2", parent: null},
{ id: "3", parent: "1" }, { id: "4", parent: "3" }
];
console.log(treeify(data, 1));
我擺脫了多余的data財產。無論如何,它并沒有在您的問題中始終如一地使用。
uj5u.com熱心網友回復:
無論如何,您都必須迭代所有資料,因此使用該迭代來反轉關系并為每個父級收集子級 ID 串列。這幾乎看起來像您想要避免的完整樹結構,但它使用的記憶體更少,因為這些陣列只包含 id,而不是物件。而且,您確實需要快速查找并避免對同一輸入進行重復迭代(例如 with find)。
這個中間結構是一個鄰接表。在第二階段,它可用于構建有限的樹物件結構:
const createAdjacencyList = data =>
data.reduce((graph, {id, parent}) =>
((graph[parent] ??= []).push(id), graph)
, {});
const createTree = (adj, depth, parent=null) =>
adj[parent].map(id => ({
id, parent,
...depth && adj[id] && {
children: createTree(adj, depth-1, id)
}
}));
// Example
const data = [{id: "1",parent: null},{id: "2",parent: null},{id: "3",parent: "1"},{id: "4",parent: "3"}];
const adj = createAdjacencyList(data);
const tree = createTree(adj, 1);
console.log(tree);
uj5u.com熱心網友回復:
此代碼使用標準遞回方法構建樹,除非達到指定的深度。在那個深度,它構建了一個平面陣列,而不是繼續構建樹。
const d = [{id:"1",parent:null},{id:"2",parent:null},
{id:"3",parent:"1"},{id:"4",parent:"3"}];
const f = (depth, p=null) => d.filter(i => i.parent===p).map(i => depth>0 ?
{data:i, children: f(depth-1, i.id)} : [{data:i}, ...f(0,i.id).flat()]);
console.log(f(1));
但是,上面的代碼將根據樹的層次結構對樹的“平面”部分進行排序。為確保“扁平”部分包含與原始資料順序相同的專案,請包含一個排序:
const d = [{id:"1",parent:null},{id:"2",parent:null},
{id:"3",parent:"1"},{id:"4",parent:"3"}];
const lookup = ({data:{id}}) => d.findIndex(d=>id===d.id);
const f = (depth, p=null) => d.filter(i => i.parent===p).map(i => depth>0 ?
{data:i, children: f(depth-1, i.id)} : [{data:i}, ...f(0,i.id).flat()]
.sort((a,b)=>lookup(a)-lookup(b)));
console.log(f(1));
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/532084.html
