从Object with Underscore.js中删除空属性/假值

Remove empty properties / falsy values from Object with Underscore.js

本文关键字:属性 假值 删除 Object with Underscore js      更新时间:2023-09-26

我有一个有几个属性的对象。我想删除所有具有假值的属性。

这可以在数组上用compact实现,但是对象呢?

从1.7.0版本开始,您可以使用_.pick:

_.pick(sourceObj, _.identity)

_.pick的第二个参数可以作为选择值的谓词函数。选取谓词返回为真的值,忽略谓词返回为假的值。

选择 _。选择(对象,*键)

返回对象的副本,过滤为只包含(或有效键数组)的值。或者接受指示选择哪个键的谓词。

_.identity是返回其第一个参数的辅助函数,这意味着它还可以作为选择真值并拒绝假值的谓词函数。Underscore库还附带了一堆其他谓词,例如_.pick(sourceObj, _.isBoolean)将只保留布尔属性。

如果你经常使用这种技巧,你可能想让它更有表现力:

var pickNonfalsy = _.partial(_.pick, _, _.identity); // Place this in a library module or something
pickNonfalsy(sourceObj);

Underscore版本1.6.0也提供了_.pick,但它不接受谓词函数而不是键列表。

你可以制作你自己的下划线插件:

_.mixin({
  compactObject: function(o) {
    _.each(o, function(v, k) {
      if(!v) {
        delete o[k];
      }
    });
    return o;
  }
});

然后将其用作本地下划线方法:

var o = _.compactObject({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined
});

更新

正如@AndreiNeculau所指出的,这个mixin会影响原始对象,而原始的compact下划线方法返回数组的副本。
为了解决这个问题,并使我们的compactObject表现得更像它的表兄弟,这里有一个小更新:

_.mixin({
  compactObject : function(o) {
     var clone = _.clone(o);
     _.each(clone, function(v, k) {
       if(!v) {
         delete clone[k];
       }
     });
     return clone;
  }
});

快速清除:_.omitBy( source, i => !i );

这与埃米尔的回答相反。这样我读起来更清楚;这是不言自明的

如果您没有ES6的奢侈,则稍微不那么干净:_.omitBy( source, function(i){return !i;});

备选:_.omitBy( source, _.isEmpty)

使用 _.isEmpty ,而不是_.identity还可以方便地从集合中删除空数组和对象,可能不方便地删除数字和日期。因此,结果并不是OP问题的确切答案,但是在寻找删除空集合时,它可能是有用的。

使用lodash的变换,

_.transform(obj, function(res, v, k) {
  if (v) res[k] = v;
});
Object.keys(o).forEach(function(k) {
    if (!o[k]) {
        delete o[k];
    }
});

您可以创建一个浅克隆:

_(obj).reduce(function(a,v,k){ 
     if(v){ a[k]=v; } 
     return a; 
},{});

为对象使用delete。

for(var k in obj){
  if(obj.hasOwnProperty(k) && !obj[k]){
    delete obj[k];
  }
}

突然,我需要创建一个函数来删除递归错误。我希望这对你有帮助。我正在使用Lodash。

var removeFalsies = function (obj) {
    return _.transform(obj, function (o, v, k) {
        if (v && typeof v === 'object') {
            o[k] = _.removeFalsies(v);
        } else if (v) {
            o[k] = v;
        }
    });
};
_.mixin({ 'removeFalsies': removeFalsies });

你可以这样写:

var o = _.removeFalsies({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined,
  obj: {
    foo: 'bar',
    a: 0,
    b: false,
    c: '',
    d: null,
    e: undefined
  }
});
// {
//   foo: 'bar',
//   obj: {
//     foo: 'bar'
//   }
// }

我确实理解这个问题是在问如何使用下划线来做这个,但由于我来自谷歌,我想添加如何使用ES6来做这个,另外,我真的很喜欢这个方法

Object.fromEntries(Object.entries(obj).filter(([k,v],i)=>v))

原因是因为它创建了一个新对象(我希望它创建一个新对象而不修改前一个对象),不使用库,不定义变量,并且不污染当前作用域。

添加到gion_13的答案:

_.mixin({
  compactObject : function(o) {
     var newObject = {};
     _.each(o, function(v, k) {
       if(v !== null && v !== undefined) {
         newObject[k] = v
       }
     });
     return newObject;
  }
});

创建一个新对象并添加键和值,而不是克隆所有内容并删除键值对。轻微的差别。

但更重要的是,显式检查null和undefined而不是falsey,这将删除值为false的键值对。

您应该使用pickBy from lodash.

pickBy的默认签名是_.(sourceObj, [_.identity]),所以它会删除空属性

_.pickBy(sourceObj);

在lodash中您这样做:

_.pickBy(object, _.identity);

尽管_.compact在文档中用于数组。它似乎也适用于对象。我刚刚在chrome, opera和firefox控制台运行了以下命令:

var obj = {first: 1, second: null, third: 3, fourth: function(){return 5}}
undefined
_.compact(obj)
[1, 3, function()]

UPDATE:正如示例所示,在对象上调用_.compact将删除键并返回一个压缩数组。