从对象的嵌套数组中删除对象

时间:2018-11-28 20:20:29

标签: javascript angular typescript multidimensional-array angular7

我有这个小功能(在我的Angular 7应用程序中),该功能使用JavaScript reduce(),并在嵌套的对象数组中定位一个对象。然后,我可以继续动态更新某些属性。

现在,除了这种查找逻辑之外,我还想将insert/delete对象嵌套嵌套数组。

问题是:找到对象后,是否可以push()和/或删除对象?

const input={UID:2,GUID:"",LocationName:"USA",ParentLocation:null,subs:[{UID:42,GUID:"",LocationName:"New Jersey",Description:"",subs:[{UID:3,GUID:"",LocationName:"Essex County",ParentLocation:null,"subs":[{UID:4,LocationName:"Newark",ParentLocation:3,"subs":[{"UID":49,"GUID":"","LocationName":"Doctor Smith's Office","LocationType":{"UID":2,"LocationTypeName":"Practice","Description":"other location"},"subs":[{"HostID":38,"HostName":"Ocean Host",}]}]}]}]}]};

const findUIDObj = (uid, parent) => {
  const { UID, subs } = parent;
  if (UID === uid) {
    const { subs, ...rest } = parent;
    return rest;
  }
  if (subs) return subs.reduce((found, child) => found || findUIDObj(uid, child), null);
};
console.log(findUIDObj(49, input));

var obj = findUIDObj(49, input);
delete obj; 

例如,在我的Angular 7应用程序中,它抱怨我是否尝试delete找到的对象:

ex /

var obj = findUIDObj(49, input);
delete obj; 

  'delete' cannot be called on an identifier in strict mode.

2 个答案:

答案 0 :(得分:2)

简要查看您的代码,我发现您正在使用const标识符来声明您的数据收集。我们仅将const用于不变的静态数据,这就是其目的。因此,首先,这似乎是问题所在。要对其进行测试,请将其更改为let。现在,关于数据管理方法,出于许多原因,不可变性值得您考虑,但是Angular会重新渲染整个对象,而不管更改现有对象或接收新对象。您可以查找不可变JavaScript以了解更多信息。在许多情况下,创建不可变数据管理是通过库完成的,您可以自己完成。基本上,创建一个名为copy( data )的函数或类似的函数,以便您传入原始对象,但是在没有引用原始对象的情况下,您将获得该函数的副本。这样一来,就不会意外更改原始对象。为此,您可以在复制功能内部执行此操作:return JSON.parse(JSON.stringify( data )) ;

您可能会遇到的唯一问题是深层嵌套对象,否则带有循环引用的对象可能会引起问题。我有一个主要的stringify方法可以在我编写的小库中进行管理。

答案 1 :(得分:1)

delete obj永远不会做您想做的事情:首先,它甚至不是您输入的对象,因为该函数从找到的对象创建了 new 对象,但不包括subs属性,并返回该属性。但更重要的是,delete用于删除属性,而不是对象。

似乎您想从其父subs属性中删除匹配的对象。为此,您需要更改subs数组,以便将匹配的对象排除在外。为了使它以通用方式工作,您的输入应为数组。否则,该根对象将无法从任何内容中删除。

请记住,您的查找函数应返回在其中找到匹配项以及在哪个索引处的数组。利用这些信息,您可以决定从数组中删除该元素,或在该索引处插入另一个对象。

这是删除时的工作方式:

const input=[{UID:2,GUID:"",LocationName:"USA",ParentLocation:null,subs:[{UID:42,GUID:"",LocationName:"New Jersey",Description:"",subs:[{UID:3,GUID:"",LocationName:"Essex County",ParentLocation:null,"subs":[{UID:4,LocationName:"Newark",ParentLocation:3,"subs":[{"UID":49,"GUID":"","LocationName":"Doctor Smith's Office","LocationType":{"UID":2,"LocationTypeName":"Practice","Description":"other location"},"subs":[{"HostID":38,"HostName":"Ocean Host",}]}]}]}]}]}];

const findUIDObj = (uid, arr) => {
    if (!arr) return;
    const idx = arr.findIndex(obj => obj.UID === uid);
    if (idx > -1) return [arr, idx];
    for (const obj of arr) {
        const result = findUIDObj(uid, obj.subs);
        if (result) return result;
    }
};
console.log(findUIDObj(49, input));

const [arr, idx] = findUIDObj(49, input) || [];
if (arr) {
    arr.splice(idx, 1); // Remove object from its parent array
}