简体   繁体   中英

Delete an object from a nested array of objects

I have this small function (within my Angular 7 application) which uses JavaScript reduce() , and locates an object within a nested array of objects. I can then proceed to update certain properties on the fly.

Now, in addition to this find logic, I would like to also insert/delete an object into/from the nested array.

Question is: once I do locate my object, can I push() and/or delete an object ?

 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; 

For example, in my Angular 7 app, it complains if I attempt to delete the found object:

ex/

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

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

Looking briefly at your code, I see you are using a const identifier to declare your data collection. We only use const for static data that does not change, and that's the purpose of it. So, first of all matters, that seems to be the problem. To test it change it to let . Now, as for methods for data management, immutability is worthy of your consideration for many reasons, but namely Angular will rerender the entire object regardless of altering the existing object, or receiveing a new object. You can look up Immutable JavaScript to understand more. In many cases, creating immutable data management is done with a library, you can do it yourself. Basically, create a function called copy( data ) , or something so that you pass in the original object, but you get a copy of it in return with no reference to the original object. That way one does not accidentally change the original object. To do this you can do this inside of your copy function: return JSON.parse(JSON.stringify( data )) ;

The only problem you might run into here is deep nested objects, or objects with circular references can cause problems. I have an overriding stringify method to mange this in little libraries I've written.

delete obj would never do what you want: first of all, it is not even an object from your input, since the function created a new object from the found object, excluding the subs property, and returned that. But more importantly, delete is used for deleting properties, not objects.

It seems you want to remove a matching object from its parent subs property. For that you would need to mutate the subs array, so it would exclude the matching object. For that to work in a generic way, your input should be an array. Otherwise that root object could not be removed from anything.

With that in mind, your lookup function should return the array in which the match was found and at which index. With those pieces of information you can decide to remove that element from the array, or to insert another object at that index.

Here is how it could work with removal:

 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 } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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