使用Underscore.js从对象中删除空属性/虚假值


83

我有一个具有多个属性的对象。我想删除任何具有虚假值的属性。

这可以通过compacton数组来实现,但是对象呢?


为了避免复制粘贴跨存储库这一点,你可以用比特导入该组件(其中有3次测试合格&MIT许可证)。您也可以尝试使用此NPM软件包(这对于小型组件来说可能是一个过大的杀伤力)。
Yoni

Answers:


47

您可以制作自己的下划线插件(mixin):

_.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 指出的那样,此混合会影响原始对象,而原始的compact下划线方法将返回数组的副本
为了解决此问题并使我们的compactObject行为更像表弟,这是一个较小的更新:

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

1
由于该问题带有下划线参考,因此最好提及此行为不像_.compact。它将删除属性,而不是仅使用真实值创建浅表克隆。见下方stackoverflow.com/a/19750822/465684
Andrei Neculau 2014年

@AndreiNeculau你是对的!我似乎早已错过了。看到我更新的答案。
gion_13 2014年

3
为什么首先复制对象的所有属性,然后遍历它们并删除伪造的属性?那太糟糕了。此外,delete通常不建议使用,因为它会立即从原型链中公开具有相同名称的属性,并且由于“隐藏类”(V8)还会损害性能-更改对象结构会导致引擎执行额外的工作。最好和最短的解决方案是_.pick(o, _.identity)
Radko Dinev 2014年

170

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

_.pick(sourceObj, _.identity)

说明

第二个参数to_.pick可以是用于选择值的谓词函数。选取谓词返回true的值,而忽略谓词返回falsy的值。

选择_.pick(object,* keys)

返回对象的副本,将其过滤为仅具有列入白名单的(或有效键的数组)的值。或者,接受一个谓词,指示要选择哪些键。

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

如果您经常使用此技术,则可能需要使其更具表现力:

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

还提供了下划线版本1.6.0 _.pick,但是它不接受谓词功能而不是白名单。


2
特别感谢您提到的_.identity功能,非常方便。
ivkremer

9
这非常方便!也可以用于_.omit(sourceObj, _.isUndefined)仅删除未定义的值(允许为false,null,0)。
本·帕特森

1
pick(obj, Boolean)消除假值也是可行的,可以使用相同的方法arr.filter(Boolean)从假值中清除数组...
David Chase

3
在ES6中,这变成了_.pick(sourceObj, prop => prop)
Deniz Ozger 2015年

16
在lodash 4.4.0中_.pick可使用属性名称,如后使用中所提到的,此功能_.pickBy
zooblin

45

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

这与Emil的回答相反。这种方式使恕我直言读起来更清晰。这更加自我解释。

如果您没有ES6的豪华版,则清洁程度略差: _.omitBy( source, function(i){return !i;});

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

使用_.isEmpty(而不是_.identity为了真实性)也可以方便地从集合中删除空数组和对象,并且可能不方便地删除数字和日期。因此,结果并不是对OP的问题的确切答案,但是在删除空集合时可能很有用。


8
在Lodash 4.0中,此功能现在位于下omitBylodash.com/docs#omitBy
JackMorrissey '16

3
我认为这与: _.pick(source, i => i); 避免否定相同
Jeff Lowery

2
@JeffLowery在Lodash中,这甚至更好,因为默认谓词是identity函数!_.pickBy(source)就是所需要的。
Shibumi

注意:数字被认为是空的。_.isEmpty(5) === true。因此,数字值将被丢弃。
森·斯塔森爵士

21

通过lodash的变换

_.transform(obj, function(res, v, k) {
  if (v) res[k] = v;
});

23
惠特·罗达斯的_.pick(obj,_.identity); 更短的^ _ ^
邪恶的2014年

这个答案或@evilive的评论就是答案。
Radko Dinev 2014年

2
根据以上评论,更短的变化将是var compactObject = _.partialRight(_.pick, _.identity);
zaboco 2014年


YSE,_.pickBy(object)是你所需要的
wdetac


9

您可以创建一个浅表克隆:

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

5

供对象使用删除。

for(var k in obj){

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

因为他想要一个下划线解决方案,所以您可以使用下划线的一种方法遍历数组
gion_13 2012年

5

突然我需要创建一个函数来递归删除虚假。我希望这有帮助。我正在使用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'
//   }
// }

1

要添加到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为值的键值对。



-1

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

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

[1, 3, function()]

更新:如样本所示,调用_.compact对象将删除键并返回压缩数组。


1
但是它仍然返回一个数组。钥匙丢了。
图拉格

1
你是对的。那我要删除答案吗?还是stackoverflow更喜欢其他东西?
tzvi

2
我不知道社区的偏爱,但是如果您愿意,可以防止他人添加类似的答案。
图拉格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.