我需要根據一個條件從樹節點中洗掉一個節點并因此獲得樹節點的更新副本
在這個答案https://stackoverflow.com/a/72121755/615274的幫助下,我到達要洗掉的節點,我將它從它所屬的陣列中排除,但回傳的節點樹不反映更改
資料如下
const data = [
{
data: 1,
children: [
{ data: 1000, children: [] },
{ data: 1200, children: [] },
],
},
{
data: 2,
children: [
{
data: 10,
children: [
{ data: 1001, children: [] },
{ data: 1201, children: [] },
{ data: 1002, children: [] },
{
data: 1201,
children: [
{ data: 111, children: [] },
{ data: 222, children: [] },
],
},
],
},
{
data: 12,
children: [
{ data: 100, children: [] },
{ data: 120, children: [] },
],
},
],
},
];
我現在使用的邏輯如下
function deleteNode(treeNode, targetId) {
if (treeNode && Array.isArray(treeNode) && treeNode.length > 0) {
for (let node of treeNode) {
if (node.data === targetId) {
treeNode = treeNode.filter((n) => n.data !== targetId);
break;
}
deleteNode(node.children, targetId);
}
}
return treeNode;
}
這標識了要洗掉的節點,將其從容器中排除,但是在回傳節點樹時,不會反映修改。
const data = [
{
data: 1,
children: [
{ data: 1000, children: [] },
{ data: 1200, children: [] },
],
},
{
data: 2,
children: [
{
data: 10,
children: [
{ data: 1001, children: [] },
{ data: 1201, children: [] },
{ data: 1002, children: [] },
{
data: 1201,
children: [
{ data: 111, children: [] },
{ data: 222, children: [] },
],
},
],
},
{
data: 12,
children: [
{ data: 100, children: [] },
{ data: 120, children: [] },
],
},
],
},
];
function deleteNode(treeNode, targetId) {
if (treeNode && Array.isArray(treeNode) && treeNode.length > 0) {
for (let node of treeNode) {
if (node.data === targetId) {
treeNode = treeNode.filter((n) => n.data !== targetId);
console.log("==== deleted node ====")
console.dir(treeNode, { depth: null });
console.log("==== deleted node ====")
break;
}
deleteNode(node.children, targetId);
}
}
return treeNode;
}
const output = deleteNode(data, 111);
console.dir(output, { depth: null });
提前致謝
uj5u.com熱心網友回復:
我經常使用deepFilter函式的變體,這讓我們可以很容易地構建一個非變異版本:
const deepFilter = (pred) => (xs) =>
xs .flatMap (({children = [], ...rest}, _, __, kids = deepFilter (pred) (children)) =>
pred (rest) || kids.length
? [{...rest, ...(kids.length ? {children: kids} : {})}]
: []
)
const deleteNode= (target) =>
deepFilter (node => node .data !== target)
const data = [{data: 1, children: [{data: 1e3, children: []}, {data: 1200, children: []}]}, {data: 2, children: [{data: 10, children: [{data: 1001, children: []}, {data: 1201, children: []}, {data: 1002, children: []}, {data: 1201, children: [{data: 111, children: []}, {data: 222, children: []}]}]}, {data: 12, children: [{data: 100, children: []}, {data: 120, children: []}]}]}]
console .log (deleteNode (111) (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
deepFilter針對您的每個輸入值測驗給定的謂詞函式,并遞回地針對它們的孩子。如果它為該值或其任何子項回傳 true,我們將該值保留在結果中。如果沒有,我們跳過它。
這讓我們可以撰寫一個簡單的deleteNode函式,只需測驗節點的data屬性是否與我們的目標值不同。
uj5u.com熱心網友回復:
問題通過以下方式解決
function deleteNode(nodes, targetId) {
if (nodes && Array.isArray(nodes) && nodes.length > 0) {
nodes.forEach((node, index) => {
if (node.data === targetId) {
nodes.splice(index, 1)
}
deleteNode(node.children, targetId)
});
}
return nodes;
}
主要變化是,現在當我洗掉元素時,我使用修改原始陣列的拼接函式來執行此操作。而且由于物件作為陣列被作為參考傳遞給函式,因此函式內部所做的每一次更改都會影響原始陣列。
可以這樣簡化
function deleteNode(nodes, targetId) {
if (nodes && Array.isArray(nodes) && nodes.length > 0) {
nodes.forEach((node, index) => {
if (node.data === targetId) {
nodes.splice(index, 1)
}
deleteNode(node.children, targetId)
});
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/475134.html
標籤:javascript 递归
