Search code examples
javascriptlodash

Can lodash remove arrays containing only null or undefined?


I have a data object that looks like this:

var obj = {
    "one":      null,
    "two":      undefined,
    "three":    [undefined],
    "four":     "valid value"
}

And I need to end up with this:

{
    "four":     "valid value"
}

I'm using lodash to try and accomplish this, and it's gotten me part way there:

obj = _.pick(obj, _identity);

Which gives me:

{
    "three":    [undefined],
    "four":     "valid value"
}

Is there a lodash-centric way to also remove not only keys whose values are null or undefined and also remove keys whose values are arrays that contain only undefined or null? I know there's a bunch of ways to do this in general, I was just wondering if lodash had some way to do this baked in.


Solution

  • You need to use _.omitBy() with _.empty() for objects (including arrays), and !value for primitives. You should also _.compact() arrays before checking if they're empty to ignore falsy values:

    var obj = {
        "one":      null,
        "two":      undefined,
        "three":    [undefined],
        "four":     "valid value",
    }
    
    var fn = o => _.omitBy(o, v => _.isObject(v) ? 
      _.isEmpty(_.isArray(v) ? _.compact(v) : v)
      : 
      !v
    )
    
    var result = fn(obj)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

    If you to remove falsy values and empty arrays/objects in a nested object/array, use _.transform() recursively. Use _.compact() to remove falsy values from arrays, and _.isEmpty() and Boolean to check:

    If you need a recursive solution you can use _.transform():

    var obj = {
        "one":      null,
        "two":      undefined,
        "three":    [undefined],
        "four":     "valid value",
        "five":     [undefined, 1],
        "six":      [{ a: null, b: [] }, undefined]
    }
    
    var cleanArray = (o) => _.isArray(o) ? _.compact(o) : o;
    
    var clean = o => _.transform(o, (r, v, k) => {
      var isObject = _.isObject(v)
      var val = isObject ? cleanArray(clean(v)) : v
      var keep = isObject ? !_.isEmpty(val) : Boolean(val)
      
      if(keep) r[k] = val
    })
    
    var result = clean(obj)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>