如何在删除某些节点后获取节点树的更新副本?
how to get an updated copy of a node tree after removing some of its nodes?
我需要根据条件从树节点中删除一个节点,并因此获得树节点的更新副本
在这个答案的帮助下我到达要删除的节点,我将它从它所属的数组中排除,但返回的节点树没有反映更改
数据如下
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 });
提前致谢
问题通过以下方式解决
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;
}
主要的变化是,现在当我删除元素时,我使用 splice 函数来修改原始数组。并且因为作为数组的对象作为引用传递给函数,所以函数内部所做的每个更改都会影响原始数组。
可以简化成这样
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)
});
}
}
我经常使用 deepFilter
函数的变体,这让我们可以很容易地构建一个 non-mutating 版本:
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
针对您的每个输入值测试给定的谓词函数,并递归地针对它们的子项。如果它 returns 对于该值或其任何子项为真,我们将该值保留在结果中。如果没有,我们跳过它。
这让我们可以编写一个简单的 deleteNode
函数,只需测试节点的 data
属性 是否与我们的目标值不同。
我需要根据条件从树节点中删除一个节点,并因此获得树节点的更新副本
在这个答案的帮助下
数据如下
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 });
提前致谢
问题通过以下方式解决
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;
}
主要的变化是,现在当我删除元素时,我使用 splice 函数来修改原始数组。并且因为作为数组的对象作为引用传递给函数,所以函数内部所做的每个更改都会影响原始数组。
可以简化成这样
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)
});
}
}
我经常使用 deepFilter
函数的变体,这让我们可以很容易地构建一个 non-mutating 版本:
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
针对您的每个输入值测试给定的谓词函数,并递归地针对它们的子项。如果它 returns 对于该值或其任何子项为真,我们将该值保留在结果中。如果没有,我们跳过它。
这让我们可以编写一个简单的 deleteNode
函数,只需测试节点的 data
属性 是否与我们的目标值不同。