简体   繁体   English

遍历嵌套数组,通过id查找特定的叶子节点,并将其删除

[英]Loop through nested array, find specific leaf node by id, and remove it

JSFiddle 的jsfiddle

I have a nested array with at most 6 levels. 我有一个最多包含6个级别的嵌套数组。 The 6th level is called gls , which holds objects of gl s from a database. 第六级称为gls ,它保存数据库中的gl s对象。 What I need to do is find a specific gl and remove it from the overall array. 我需要做的是找到一个特定的gl并将其从整个数组中删除。 I'm able to find the specific element with the following function; 我可以使用以下功能找到特定的元素;

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);
    }
  });
}

However, I'm struggling to actually remove it from the data array. 但是,我正在努力从data数组中删除它。 Trying to get the index by doing data.indexOf(gl) obviously returns -1 as it doesn't search through the nested elements. 试图通过执行data.indexOf(gl)来获取索引显然会返回-1因为它不会搜索嵌套的元素。 What's the best way to accomplish this? 做到这一点的最佳方法是什么?

 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 passes three arguments to the callback, the second of which is the index of the entry being visited. forEach将三个参数传递给回调,第二个参数是要访问的条目的索引。 So you can use that index with splice (if you want to modify in place): 因此,您可以将该索引与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);
    }
  });
}

I notice you're using some , which suggests you want to stop when you've found the entry and perhaps also return a flag indicating success/failure. 我注意到您正在使用some ,这表明您希望在找到条目后停止,并且还可能返回指示成功/失败的标志。 If so, I'd use some instead of forEach on the nodes.gls search or possibly use findIndex instead. 如果是这样,我会在nodes.gls搜索上使用some代替而不是forEach ,或者可能使用findIndex代替。 With some : 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);
    }
  });
}

With findIndex : 随着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);
    }
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM