javascript - 遍历嵌套数组,通过id找到特定的叶子节点,并将其移除
问题描述
我有一个最多有 6 个级别的嵌套数组。第 6 层称为gls
,它保存gl
数据库中 s 的对象。我需要做的是找到一个特定的gl
并将其从整个阵列中删除。我能够找到具有以下功能的特定元素;
const removeFromData = function(nodes, id) {
return nodes.some((node) => {
if (node.gls) {
node.gls.forEach((gl) => {
if (gl.id === id) {
console.log(gl, id);
}
});
} else if (node.children) {
return removeFromData(node.children, id);
}
});
}
但是,我正在努力将其从data
阵列中实际删除。尝试通过执行来获取索引data.indexOf(gl)
显然会返回-1
,因为它不会搜索嵌套元素。实现这一目标的最佳方法是什么?
const id = 1000;
const data = [{
"id": 1, "name": "Node 1", "children": [{
"id": 2, "name": "Node 1.1", "children": [{
"id": 4, "name": "Node 1.1.1", "leaf": true, "children": [], "gls": [{
"id": 1000, "name": "GL1", "code": "0100"
}, {
"id": 1001, "name": "GL2", "code": "0200"
}]
}, {
"id": 5, "name": "Node 1.1.2", "leaf": true, "children": [], "gls": [{
"id": 2000, "name": "GL3", "code": "0300"
}, {
"id": 2001, "name": "GL4", "code": "0400"
}]
}]
}, {
"id": 3, "name": "Node 1.2", "children": [{
"id": 6, "name": "Node 1.2.1", "leaf": true, "children": [], "gls": [{
"id": 3000, "name": "GL5", "code": "0500"
}, {
"id": 3001, "name": "GL6", "code": "0600"
}]
}]
}]
},
{
"id": 7, "name": "Node 2", "children": [{
"id": 8, "name": "Node 2.1", "children": [{
"id": 9, "name": "Node 2.1.1", "leaf": true, "children": [], "gls": [{
"id": 4000, "name": "GL7", "code": "0700"
}, {
"id": 4001, "name": "GL8", "code": "0800"
}]
}]
}]
}
];
let removeFromData = function(nodes, id) {
return nodes.some((node) => {
if (node.gls) {
node.gls.forEach((gl) => {
if (gl.id === id) {
document.querySelector('#target').innerText = `found ${gl.name}, ${gl.id} with needle ${id}`;
}
});
} else if (node.children) {
return removeFromData(node.children, id);
}
});
}
removeFromData(data, id);
<p id="target"></p>
解决方案
forEach
将三个参数传递给回调,其中第二个是被访问条目的索引。因此,您可以使用该索引splice
(如果您想就地修改):
const removeFromData = function(nodes, id) {
return nodes.some((node) => {
if (node.gls) {
node.gls.forEach((gl, index) => {
// -----------------------^^^^^^^
if (gl.id === id) {
//console.log(gl, id);
node.gls.splice(index, 1); // <=== Removes the entry
}
});
} else if (node.children) {
return removeFromData(node.children, id);
}
});
}
我注意到您正在使用some
,这表明您希望在找到该条目时停止,并且可能还返回一个指示成功/失败的标志。如果是这样,我会使用而some
不是搜索或可能使用。与:forEach
nodes.gls
findIndex
some
const removeFromData = function(nodes, id) {
return nodes.some((node) => {
if (node.gls) {
return node.gls.some((gl, index) => {
if (gl.id === id) {
//console.log(gl, id);
node.gls.splice(index, 1); // <=== Removes the entry
return true;
}
});
} else if (node.children) {
return removeFromData(node.children, id);
}
});
}
与findIndex
:
const removeFromData = function(nodes, id) {
return nodes.some((node) => {
if (node.gls) {
const index = node.gls.findIndex((gl) => {
return gl.id === id;
});
if (index === -1) {
return false;
}
node.gls.splice(index, 1);
return true;
} else if (node.children) {
return removeFromData(node.children, id);
}
});
}
推荐阅读
- logic - 如何将 Coq 用作计算器或前向链接规则引擎/序列应用工具?
- woocommerce - 从 Woocommerce 电子邮件通知中隐藏重力形式字段标签
- python - 如何在 Windows 10 上沙箱学生的 Python 3 代码提交以进行自动作业评估?
- c# - 如何在没有互联网的情况下在树莓派上包含 nuget 包?
- ruby-on-rails - 无法将 Ruby gem Gibbon 与 MailChimp API 链接起来
- javascript - 如何使用来自服务器的 FCM 向用户发送推送通知?
- julia - 如何在for循环中更改变量的名称
- actions-on-google - 为智能家居操作启用测试/模拟器时,“我们很抱歉,出了点问题,请重试”
- php - 如何修复 Laravel 电子邮件问题
- javascript - 隐藏 div 仅在 Ajax 响应的所有内容都已呈现后