【问题标题】:How to delete object from an array of objects having relations with each arrays?如何从与每个数组有关系的对象数组中删除对象?
【发布时间】:2018-07-16 05:07:52
【问题描述】:

此对象的关系为: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],那么它下面的所有相关对象也应该被删除)。

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

【问题讨论】:

  • 简短回答:不,没有什么神奇的方法可以让它理解你的结构并递归删除对象。您需要编写代码(只需编写好并测试它 - 然后它就不会“错误”)
  • 如果你手动定义这样的标题的父子顺序,而不是在数据结构中反映顺序,就不会有免费的午餐。您必须以一种或另一种方式使用此信息“childOne > childTwo > childThree > childFour > childFive > childSix”。
  • @Mehdi 我将对象键作为方法的参数。它可以是任何级别。
  • 那么,@S.Negi 你是说,parentObj.childOne 中的一个项目可能有一个像“childFive”这样的键,例如像“44444”这样的值?
  • 删除功能是什么样的? removeItem("childOne",obj.parentElement)?

标签: javascript arrays angularjs algorithm recursion


【解决方案1】:

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

  • 本质上,对象具有一组无序的属性,因此无法保证迭代parentObj 的属性会给您提供childOnechildTwochildThree 的顺序...实际上此顺序由创建这些属性的顺序决定,但对此没有书面保证。因此,人们可能会先于父母找到孩子,反之亦然。
  • 虽然这样的child 数组中的id 值应该是唯一的,但此对象结构并不能保证这一点。而且,给定一定的id值,不可能在恒定时间内找到对应的对象。

鉴于这种结构,似乎最好先添加一个哈希来解决上述缺点。用于了解节点组(通过 id)的对象和用于了解下一级组名的对象可以对此有所帮助。

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

这是与 ES5 兼容的代码(因为您在 cmets 中提到不支持 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; }

【讨论】:

  • 非常感谢您的努力。你已经用 ES6 编写了代码,所以我使用 Babel 编译它。但是输出不正确。
  • “输出不正确”。请解释。据我所知,sn-p 显示正确的输出。
  • 您的程序仅删除通过该方法传递的对象。但它不会删除与该对象相关的子根。
  • 但它是:请检查 sn-p:看看它如何删除 id=1111 的节点的所有后代。您一定是错误地实现了它。
  • 我更新了答案。现在在问题中使用新的 parent_id 结构,并且只使用 ES5,而不是 ES6。
【解决方案2】:

当然,用于删除条目的函数应该首先递归,这意味着在链接的条目上运行自身,除非没有。所以,在伪代码中

function del(name, index)
{
    if parent[name][index]  has reference
    Then del(reference name, reference ID)
    Now del parent[name][index] 
}

不需要循环。 而且由于如果没有引用就停止,因此我们不会永远递归。

【讨论】:

  • 感谢您修复格式,我刚开始回答问题。
  • 你有对象,请写实现。
  • 嗨,s.negi!我没有编写实现的原因(除了在移动设备上)是我不确定您的对象是否足以编写它。每个子项可以有多个条目,但您要删除的条目在引用中不存在。我也不完全确定我是否有足够的关于您的用例的信息来以最佳方式编写它。通过提供伪代码,我希望能给你提供我所能提供的所有帮助,以便你可以编写它,因为你有更多的信息。
  • 另外,从你的措辞看来,你似乎没有理解算法必须做的基本操作(递归),我的回答是为了解释它。
  • 这个对象已经足够解决问题了。如果您想了解更多信息,请告诉我。
【解决方案3】:

不确定你想要什么,但也许这会起作用:

const someObject = {
  "parentObj": {
    "childOne": [
      {
        "name": "A",
        "id": "1"
      },
      {
        "name": "B",
        "id": "2"
      }
    ],
    "childTwo": [
      {
        "name": "AB",
        "childOne": "1",
        "id": "11"
      },
      {
        "name": "DE",
        "childOne": "2",
        "id": "22"
      }
    ]
  }
};
const removeByID = (key,id,parent) =>
  Object.keys(parent).reduce(
    (o,k)=>{
      o[k]=parent[k].filter(
        item=>
          !(Object.keys(item).includes(key)&&item[key]===id)
      );
      return o;
    },
    {}
  );

const withoutID = Object.assign(
  {},
  someObject,
  { parentObj : removeByID("childOne","1",someObject.parentObj) }
);
console.log(`notice that childTwo item with childOne:"1" is gone`);
console.log("without key:",JSON.stringify(withoutID,undefined,2));

const otherExample = Object.assign(
  {},
  someObject,
  { parentObj : removeByID("childOne","2",someObject.parentObj) }
);
console.log(`notice that childTwo item with childOne:"2" is gone`);
console.log("without key:",JSON.stringify(otherExample,undefined,2));

const both = Object.assign(
  {},
  someObject,
  { parentObj : removeByID("childOne","1",otherExample.parentObj) }
);
console.log(`notice that childTwo items with childOne are both gone`);
console.log("without key:",JSON.stringify(both,undefined,2));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    相关资源
    最近更新 更多