javascript - 如何从与每个数组有关系的对象数组中删除对象?

标签 javascript arrays angularjs algorithm recursion

此对象的关系为:childOne> childTwo> childThree> childFour> childFive> childSix

{
  "parentObj": {
    "childOne": [
      {
        "name": "A",
        "id": "1"
      },
      {
        "name": "B",
        "id": "2"
      }
    ],
    "childTwo": [
      {
        "name": "AB",
        "parent_id": "1",
        "id": "11"
      },
      {
        "name": "DE",
        "parent_id": "2",
        "id": "22"
      }
    ],
    "childThree": [
      {
        "name": "ABC",
        "parent_id": "22",
        "id": "111"
      },
      {
        "name": "DEF",
        "parent_id": "11",
        "id": "222"
      }
    ],
    "childFour": [
      {
        "name": "ABCD",
        "parent_id": "111",
        "id": "1111"
      },
      {
        "name": "PQRS",
        "parent_id": "111",
        "id": "2222"
      }
    ],
    "childFive": [
      {
        "name": "FGRGF",
        "parent_id": "1111",
        "id": "11111"
      },
      {
        "name": "ASLNJ",
        "parent_id": "1111",
        "id": "22222"
      },
      {
        "name": "ASKJA",
        "parent_id": "1111",
        "id": "33333"
      }
    ],
    "childSix": [
      {
        "name": "SDKJBS",
        "parent_id": "11111",
        "id": "111111"
      },
      {
        "name": "ASKLJB",
        "parent_id": "11111",
        "id": "222222"
      }
    ]
  }
}

有没有办法通过 ID 删除项目,并且应该删除与该特定 ID 关联的对象(即,如果我执行 delete parentObj.childTwo[1],那么所有它下面的相关对象也应该被删除。

手动循环是太糟糕的代码,并且会产生错误。必须有更好的方法来处理此类问题,例如递归或其他。

最佳答案

数据结构不允许有效操作:

  • 本质上,对象具有一组无序的属性,因此无法保证迭代 parentObj 的属性会给您 childOne 的顺序, childTwo, childThree, ... 在实践中,这个顺序是由这些属性的创建顺序决定的,但没有记录在案的保证。因此,人们可能会先找到 child ,然后再找到 parent ,反之亦然。
  • 虽然这样的 child 数组中的 id 值应该是唯一的,但此对象结构并不能保证这一点。而且,给定一个id值,不可能在常数时间内找到对应的对象。

鉴于这种结构,似乎最好先添加一个散列来解决上述缺点。用于了解节点组(按 ID)的对象和用于了解下一级组名称的对象可以帮助解决这个问题。

以上两个任务可以在O(n)时间内执行,其中n为节点数。

这是兼容 ES5 的代码(因为您在评论中提到不支持 ES6)。它提供了一个示例调用,其中将 ID 为“1111”的节点从您的示例数据中删除,并打印生成的对象。

function removeSubTree(data, id) {
    var groupOf = {}, groupAfter = {}, group, parents, keep = { false: [], true: [] };

    // Provide link to group per node ID
    for (group in data) {
        data[group].forEach(function (node) {
            groupOf[node.id] = group;
        });
    }
    // Create ordered sequence of groups, since object properties are not ordered
    for (group in data) {
        if (!data[group].length || !data[group][0].parent_id) continue;
        groupAfter[groupOf[data[group][0].parent_id]] = group;
    }
    // Check if given id exists:
    group = groupOf[id];
    if (!group) return; // Nothing to do
    // Maintain list of nodes to keep and not to keep within the group
    data[group].forEach(function (node) {
        keep[node.id !== id].push(node);
    });
    while (keep.false.length) { // While there is something to delete
        data[group] = keep.true; // Delete the nodes from the group
        if (!keep.true.length) delete data[group]; // Delete the group if empty
        // Collect the ids of the removed nodes
        parents = {};
        keep.false.forEach(function (node) {
            parents[node.id] = true;
        });
        group = groupAfter[group]; // Go to next group
        if (!group) break; // No more groups
        // Determine what to keep/remove in that group
        keep = { false: [], true: [] };
        data[group].forEach(function (node) {
            keep[!parents[node.parent_id]].push(node);
        });
    }
}

var tree = {"parentObj": {"childOne": [{"name": "A","id": "1"},{"name": "B","id": "2"}],"childTwo": [{"name": "AB","parent_id": "1","id": "11"},{"name": "DE","parent_id": "2","id": "22"}],"childThree": [{"name": "ABC","parent_id": "22","id": "111"},{"name": "DEF","parent_id": "11","id": "222"}],"childFour": [{"name": "ABCD","parent_id": "111","id": "1111"},{"name": "PQRS","parent_id": "111","id": "2222"}],"childFive": [{"name": "FGRGF","parent_id": "1111","id": "11111"},{"name": "ASLNJ","parent_id": "1111","id": "22222"},{"name": "ASKJA","parent_id": "1111","id": "33333"}],"childSix": [{"name": "SDKJBS","parent_id": "11111","id": "111111"},{"name": "ASKLJB","parent_id": "11111","id": "222222"}]}}

removeSubTree(tree.parentObj, "1111");

console.log(tree.parentObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 如何从与每个数组有关系的对象数组中删除对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48637895/

相关文章:

javascript - 在函数外部使用 jquery 变量

javascript - 根据数组 javascript 中的日期和名称进行过滤、匹配、计算

javascript - 单页上的两个模块在 Angular js 中不起作用

node.js - 推送到heroku的提交文件夹没有成功

javascript - 如何获得垂直对齐元素的正确顶部位置?

javascript - 在 AngularJS 中按数字过滤数组

arrays - Excel VBA 将范围值复制到数组,

java - 将两个二维数组扩展为一个更大的数组

javascript - 城市和州正则表达式模式

javascript - Angular Universal 和浏览器功能检查