JavaScript deeply removes the property of an object using another object as a selector

I have an object like this:

var myObj = { first: { sub: { prop1: "some text", prop2: "some more text" }, sub2: { prop1: "Something", prop2: "Something2", } }, second: { stuff: "More stuff...lots of stuff" } } 

I am trying to remove a property from this object using another object as a selector. For instance:

 var delSeletor = { first: { sub: { prop2: "" } } } 

So delete( delSelector, myObject) should return:

 var myObj = { first: { sub: { prop1: "some text", }, sub2: { prop1: "Something", prop2: "Something2", } }, second: { stuff: "More stuff...lots of stuff" } } 

Note that I am not looking for a solution using the ".dot" selector, for example: delete('first.sub.prop2', myObj) , as shown in this.

+5
source share
2 answers

You can iterate the selector object for keys to delete and check

  • If the key does not exist, return
  • If the property of the selector object is an object, then call the deleteKeys delete function deleteKeys with the key. Otherwise, delete the key form of the source object.

 function deleteKeys(object, selector) { Object.keys(selector).forEach(function (k) { if(!(k in object)) { return; } if (typeof selector[k] === 'object') { deleteKeys(object[k], selector[k]); } else { delete object[k]; } }); } var myObj = { first: { sub: { prop1: "some text", prop2: "some more text" }, sub2: { prop1: "Something", prop2: "Something2", } }, second: { stuff: "More stuff...lots of stuff" } }, delSeletor = { first: { sub: { prop2: "" } } }; deleteKeys(myObj, delSeletor); console.log(myObj); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
+3
source

Here is a version that uses functional programming with map and reduce .

It recursively intersects both objects and deletes keys that are marked with an empty string on the object representing the deletes

 function deleteKeys(deletions, obj) { if (deletions === "") { return null } return Object .keys(obj) .map(key => { if (!(key in deletions)) { // if the key is not in the object containing // the keys to delete return { [key]: obj[key] }; } //recursively create a filtered object const filteredObj = deleteKeys(deletions[key], obj[key]) // if that object is null, then return an empty object // else return the filtered object return filteredObj ? { [key]: filteredObj } : {} }) // we now have an array of object that we need to merge together :) .reduce((acc, obj) => Object.assign({}, acc, obj), {}) } 

Here are the tests I ran to encode this:

 const cleanedObj = deleteKeys( { first: "" }, { first: "", second: { hi: ["heelo"] }} ); console.log(cleanedObj); const cleanedObj2 = deleteKeys( { second: { hi: "" }}, { first: "", second: { hi: ["heelo"] }} ); console.log(cleanedObj2); const cleanedObj3 = deleteKeys( { second: "" }, { first: "", second: { hi: ["heelo"] }} ); console.log(cleanedObj3); 

It is worth noting that this solution is a pure function ( https://en.wikipedia.org/wiki/Pure_function ), which means they will not change their original object, but instead will return a new one. No side effects of FTW

0
source

Source: https://habr.com/ru/post/1268437/


All Articles