从嵌套的对象数组中删除一个对象
Delete an object from a nested array of objects
我有这个小函数(在我的 Angular 7
应用程序中),它使用 JavaScript reduce()
,并在嵌套的对象数组中定位一个对象。然后我可以继续动态更新某些属性。
现在,除了这个查找逻辑,我还想 insert/delete
一个对象 into/from 嵌套数组。
问题是:一旦找到我的对象,我可以 push() and/or 删除一个对象吗?
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.
delete obj
永远不会做你想做的事:首先,它甚至不是你输入的对象,因为该函数从找到对象,不包括 subs
属性 和 returned。但更重要的是,delete
用于删除属性,而不是对象。
您似乎想从其父对象中删除一个匹配对象 subs
属性。为此,您需要改变 subs
数组,以便排除匹配的对象。为了以通用方式工作,您的输入应该是一个数组。否则无法从任何对象中删除该根对象。
考虑到这一点,您的查找函数应该 return 在其中找到匹配项的数组以及在哪个索引处。使用这些信息,您可以决定从数组中删除该元素,或在该索引处插入另一个对象。
以下是它如何处理删除:
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
}
简要查看您的代码,我发现您正在使用 const
标识符来声明您的数据收集。我们只对不会改变的静态数据使用const
,这就是它的目的。所以,首先,这似乎是问题所在。要对其进行测试,请将其更改为 let
。现在,至于数据管理方法,不可变性值得您考虑,原因有很多,但即 Angular 将重新呈现整个对象,而不管更改现有对象或接收新对象。您可以查看 Immutable JavaScript 以了解更多信息。在许多情况下,创建不可变数据管理是通过库完成的,您可以自己完成。基本上,创建一个名为 copy( data )
或其他名称的函数,以便您传入原始对象,但您会在 return 中获得它的副本,而不会引用原始对象。这样就不会不小心更改原始对象。为此,您可以在复制功能中执行此操作:return JSON.parse(JSON.stringify( data )) ;
您可能 运行 进入这里的唯一问题是深层嵌套对象,或者具有循环引用的对象可能会导致问题。我有一个压倒一切的 stringify
方法来管理我写的小库中的这个。
我有这个小函数(在我的 Angular 7
应用程序中),它使用 JavaScript reduce()
,并在嵌套的对象数组中定位一个对象。然后我可以继续动态更新某些属性。
现在,除了这个查找逻辑,我还想 insert/delete
一个对象 into/from 嵌套数组。
问题是:一旦找到我的对象,我可以 push() and/or 删除一个对象吗?
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.
delete obj
永远不会做你想做的事:首先,它甚至不是你输入的对象,因为该函数从找到对象,不包括 subs
属性 和 returned。但更重要的是,delete
用于删除属性,而不是对象。
您似乎想从其父对象中删除一个匹配对象 subs
属性。为此,您需要改变 subs
数组,以便排除匹配的对象。为了以通用方式工作,您的输入应该是一个数组。否则无法从任何对象中删除该根对象。
考虑到这一点,您的查找函数应该 return 在其中找到匹配项的数组以及在哪个索引处。使用这些信息,您可以决定从数组中删除该元素,或在该索引处插入另一个对象。
以下是它如何处理删除:
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
}
简要查看您的代码,我发现您正在使用 const
标识符来声明您的数据收集。我们只对不会改变的静态数据使用const
,这就是它的目的。所以,首先,这似乎是问题所在。要对其进行测试,请将其更改为 let
。现在,至于数据管理方法,不可变性值得您考虑,原因有很多,但即 Angular 将重新呈现整个对象,而不管更改现有对象或接收新对象。您可以查看 Immutable JavaScript 以了解更多信息。在许多情况下,创建不可变数据管理是通过库完成的,您可以自己完成。基本上,创建一个名为 copy( data )
或其他名称的函数,以便您传入原始对象,但您会在 return 中获得它的副本,而不会引用原始对象。这样就不会不小心更改原始对象。为此,您可以在复制功能中执行此操作:return JSON.parse(JSON.stringify( data )) ;
您可能 运行 进入这里的唯一问题是深层嵌套对象,或者具有循环引用的对象可能会导致问题。我有一个压倒一切的 stringify
方法来管理我写的小库中的这个。