使用Underscore.js从Object中删除空属性/ falsy值

81 javascript arrays object underscore.js

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

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

Emi*_*erg 167

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

_.pick(sourceObj, _.identity)
Run Code Online (Sandbox Code Playgroud)

说明

第二个参数_.pick可以是用于选择值的谓词函数.将选择谓词返回值的值,并忽略谓词返回值的值.

选择 _.pick(对象,*键)

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

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

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

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

提供了Underscore版本1.6.0 _.pick,但它不接受谓词函数而不是白名单.

  • 在lodash 4.4.0``.pick`中使用属性名称,对于此功能,如帖子中提到的`_.pickBy` (16认同)
  • 这非常方便!也可以使用`_.omit(sourceObj,_.isUndefined)`来仅删除未定义的值(允许false,null,0). (9认同)
  • 在ES6中,这变成了```_pick(sourceObj,prop => prop)``` (3认同)
  • 特别感谢提及`_.identity`功能,非常方便. (2认同)

gio*_*_13 47

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

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

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

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

更新

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

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

  • 为什么首先复制一个对象的所有属性,然后遍历它们并删除虚假对象?那是不合情理的.此外,通常不建议使用`delete`,因为它会立即从原型链中公开具有相同名称的属性,并且由于"隐藏类"(V8)而损害性能 - 更改对象结构会导致引擎执行额外的工作.最好和最短的解决方案是`_.pick(o,_.identity)`. (3认同)

Shw*_*ogg 45

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

这与Emil的答案相反.这样imho读得更清楚; 它更加自我解释.

如果你没有ES6的奢侈品,那就不那么干净了: _.omit( source, function(i){return !i;});

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

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

  • 在Lodash 4.0中,此功能现在位于`omitBy`下.https://lodash.com/docs#omitBy (8认同)
  • 我相信这与:``_.pick(source,i => i);`''相同,它避免了否定 (3认同)
  • @JeffLowery在Lodash中,这甚至更好,因为默认谓词是identity函数!只需_.pickBy(source)即可。 (2认同)

rai*_*ine 21

随着lodash的改造,

_.transform(obj, function(res, v, k) {
  if (v) res[k] = v;
});
Run Code Online (Sandbox Code Playgroud)

  • whit lodash的_.pick(obj,_.identity); 更短^ _ ^ (23认同)
  • @zaboco [在lodash v4中它应该是`_.pickBy`而不是`_.pick`](http://stackoverflow.com/questions/39503069/what-has-changed-in-lodash-from-3-to -4-那此结果代码是 - 不工作/ 39503305#39503305)) (4认同)
  • 基于上述注释的较短变化将是`var compactObject = _.partialRight(_.pick,_.identity);` (2认同)

Flo*_*ine 17

Object.keys(o).forEach(function(k) {
    if (!o[k]) {
        delete o[k];
    }
});
Run Code Online (Sandbox Code Playgroud)

  • +1用于选择变量名称,OK :) (7认同)

web*_*ise 9

您可以创建浅克隆:

_(obj).reduce(function(a,v,k){ 
     if(v){ a[k]=v; } 
     return a; 
},{});
Run Code Online (Sandbox Code Playgroud)


Ano*_*oop 5

用于对象使用删除.

for(var k in obj){

  if(obj.hasOwnProperty(k) && !obj[k]){
    delete obj[k];
  }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*nez 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 });
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它:

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'
//   }
// }
Run Code Online (Sandbox Code Playgroud)