0

I have a large javascript object which contains multiple instances of a key. I'd like to remove all instances of this key and value from the object.

I have this function which allows me to find a nested object, though I'm not sure how to modify it to get all objects, and to delete the keys from the object. Can someone help me with this?

var findObjectByKey= function (o, key) {
  if (!o || (typeof o === 'string')) {
    return null
  }
  if (o[key]) {
    return o[key];
  }

  for (var i in o) {
    if (o.hasOwnProperty(i)) {
      var found = findObjectByKey(o[i], key)
      if (found) {
        return found
      }
    }
  }
  return null
}

This is an example object where I'd like to remove all keys d:

var a = {
  b: {
    c: {
      d: 'Hello',
    },
    d: 'Hola',
    e: {
      f: {
        d: 'Hey'
      }
    }
  }
}

// To become
var a = {
  b: {
    c: {},
    e: {
      f: {}
    }
  }
}

Also, is there a way we could do this with Ramda by chance?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
alexmngn
  • 9,107
  • 19
  • 70
  • 130

2 Answers2

3

Using R.when, if o is an object, apply R.pipe to it. In the pipe, remove the property from the object using R.dissoc. Iterate other properties with R.map, and try to remove the property for each of them.

const removePropDeep = R.curry((prop, o) => R.when(
  R.is(Object),
  R.pipe(
    R.dissoc(prop),
    R.map(removePropDeep(prop))
  ),
  o
))

const a = {
  b: {
    c: {
      d: 'Hello',
    },
    d: 'Hola',
    e: {
      f: {
        d: 'Hey'
      }
    }
  }
}

const result = removePropDeep('d')(a)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Be aware. This will turn arrays to objects https://ramdajs.com/repl/?v=0.28.0#?const%20removePropDeep%20%3D%20R.curry%28%28prop%2C%20o%29%20%3D%3E%0A%20%20R.when%28R.is%28Object%29%2C%20R.pipe%28R.dissoc%28prop%29%2C%20R.map%28removePropDeep%28prop%29%29%29%2C%20o%29%2C%0A%29%0A%0AremovePropDeep%28%27b%27%2C%20%7Bhi%3A%20%7Ba%3A%20%5B1%2C%202%2C%203%5D%7D%7D%29 – moto May 09 '22 at 19:21
1

To alter the object in place you can just change:

return o[key];

to:

delete o[key];

To return a new object, make a new object with Object.assign(), then delete the key in question. Then recurse on the rest of the keys:

var a = {
  b: {
    c: {
      d: 'Hello',
    },
    d: 'Hola',
    e: {
      f: {
        d: 'Hey'
      }
    }
  }
}

var findObjectByKey= function (o, key) {
  if (!o || (typeof o === 'string')) {    //  assumes all leaves will be strings
    return o
  }
  o = Object.assign({}, o)                // make a shallow copy
  if (o[key]) {
    delete o[key]                         // delete key if found
  }
  Object.keys(o).forEach( k => {
      o[k] = findObjectByKey(o[k], key)   // do the same for children
    })
  return o                                // return the new object
}

let obj = findObjectByKey(a, 'd')
console.log(obj)
Mark
  • 90,562
  • 7
  • 108
  • 148