如何使用lodash从对象中删除未定义和空值?


172

我有一个Javascript对象,例如:

var my_object = { a:undefined, b:2, c:4, d:undefined };

如何删除所有未定义的属性?错误的属性应该保留。

Answers:


195

如果要删除所有错误值,则最紧凑的方法是:

对于Lodash 4.x和更高版本

_.pickBy({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}

对于旧版 Lodash 3.x:

_.pick(obj, _.identity);

_.pick({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}

63
请注意,在lodash 4中应为_.pickBy(obj, _.identity);
Tom Spencer

30
请注意,此方法还将删除错误的值。
无限

12
请注意,这将删除布尔其财产falseVALU
西拉姆

6
除了删除false之外,它还会删除属性0和''作为属性...不是一个好主意。
Federico Budassi '18

4
这个答案不是正确的,因为它也消除了虚假的值。在下面检查我的答案。
TiagoBértolo19年

224

您可以简单地_.omit()_.isUndefined_.isNull组成链,然后通过惰性评估获得结果。

演示版

var result = _(my_object).omit(_.isUndefined).omit(_.isNull).value();

更新2016年3月14日

如注释部分中dylants所述,您应该使用该_.omitBy()函数,因为它使用谓词而不是属性。您应该将其用于lodash版本4.0.0及更高版本。

演示

var result = _(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();

更新2016年6月1日

正如Max Truxa所评论的那样,lodash已经提供了另一种选择_.isNil,它可以同时检查nullundefined

var result = _.omitBy(my_object, _.isNil);

7
那些使用lodash的最新版本的用户应使用omitBy函数而不是omit。所以_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants

31
从lodash 4.0.0开始,您可以使用_.isNil而不是链接_.isUndefined_.isNull。这使它变得更短:var result = _.omitBy(my_object, _.isNil);
Max Truxa

@MaxTruxa您如何修改它以递归检查“ Nil”值?
2016年

1
Lodash的omitBy性能不如pickBy,因此后者是首选,并且iteratee函数中的条件相反。上面接受的答案是正确的。
Ernesto

1
OP的问题仅指定nullundefined值。该identity谓词也将删除false值,所以如果你只是基于它在这个问题的意图,然后我看不出我的回答的一个问题。另外,如果我们要讨论“性能”,则默认情况下,omitBy只需pickBy使用否定identity谓词进行调用即可。因此,就性能而言,它太小了以至于不重要。
ryeballar '18

38

如果使用lodash,则可以用来_.compact(array)从数组中删除所有错误的值。

_.compact([0, 1, false, 2, '', 3]);
// => [1, 2, 3]

https://lodash.com/docs/4.17.4#compact


36
紧凑适用于数组,但问题在于对象
guidoman

1
除了我想保持0。Argh,如此接近。
Sammi

2
@Sammi,_.pickBy(object, _.isNumber)在这种情况下可以使用。
John Rix

1
谢谢@Herick。这样可行。我现在就去睡觉。
technophyle

1
@technophyle,我同意你的观点(我是写这个答案的人,哈)。但是我在这里保留这个答案,因为它至少可以解决一些人的问题。
JavaFish

25

正确答案是:

_.omitBy({ a: null, b: 1, c: undefined, d: false }, _.isNil)

结果是:

{b: 1, d: false}

其他人在这里给出的替代方案:

_.pickBy({ a: null, b: 1, c: undefined, d: false }, _.identity);

还将删除false此处不需要的值。


{"a":1,"b":{"a":1,"b":null,"c":undefined}},object.b属性b,“ c”将不会删除
mqliutie

@mqliutie符合预期。
TiagoBértolo,

18

只是:

_.omit(my_object, _.isUndefined)

上面没有考虑null值,因为它们是原始示例中缺少的,仅在主题中提到,但是我保留了它,因为它很雅致并且可能有其用途。

这是完整的示例,简洁程度不高,但更完整。

var obj = { a: undefined, b: 2, c: 4, d: undefined, e: null, f: false, g: '', h: 0 };
console.log(_.omit(obj, function(v) { return _.isUndefined(v) || _.isNull(v); }));

8
请注意,这是针对Lodash v.3的。对于v.4,您必须使用_.omitBy
PhiLho

16

要完成其他答案,请在lodash 4中仅忽略undefined和null(并且不忽略诸如的属性false),可以在中使用谓词_.pickBy

_.pickBy(obj, v !== null && v !== undefined)

下面的例子:

const obj = { a: undefined, b: 123, c: true, d: false, e: null};

const filteredObject = _.pickBy(obj, v => v !== null && v !== undefined);

console.log = (obj) => document.write(JSON.stringify(filteredObject, null, 2));
console.log(filteredObject);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>


1
如果您不想删除,值0,这是最好的解决方案。您也可以将回调缩短为。''falsev => v != null
SimpleJ

2
简单的解决方案。这次真是万分感谢。
Arjun G Perambra '18


6

对于深层嵌套对象,您可以将我的代码段用于lodash> 4

const removeObjectsWithNull = (obj) => {
    return _(obj)
      .pickBy(_.isObject) // get only objects
      .mapValues(removeObjectsWithNull) // call only for values as objects
      .assign(_.omitBy(obj, _.isObject)) // save back result that is not object
      .omitBy(_.isNil) // remove null and undefined from object
      .value(); // get value
};

5

undefined从深层对象中删除时遇到了类似的问题,发现如果您可以转换普通的旧对象并使用JSON,则快速而肮脏的帮助器函数将如下所示:

function stripUndefined(obj) {
  return JSON.parse(JSON.stringify(obj));
}

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description

“ ...如果在转换过程中遇到未定义的函数或符号,则将其省略(当在对象中找到时)或将其检查为空(当在数组中找到时)。


5

使用纯JavaScript :(尽管Object.entries是ES7,Object.assign是ES6;但是等效的ES5仅使用Object.keys也应该可行);还要注意v != null检查null和undefined;

> var d = { a:undefined, b:2, c:0, d:undefined, e: null, f: 0.3, s: "", t: false };
undefined
> Object.entries(d)
    .filter(([ k, v ]) => (v != null))
    .reduce((acc, [k, v]) => Object.assign(acc, {[k]: v}), {})
{ b: 2, c: 0, f: 0.3, s: '', t: false }

编辑:以下是仅带有ES5 Object.keys的版本:但通常在Node v8中使用ES7相当有趣;-)

> Object.keys(d)
    .filter(function(k) { return d[k] != null; })
    .reduce(function(acc, k) { acc[k] = d[k]; return acc; }, {});
{ b: 2, c: 0, f: 0.3, s: '', t: false }

2017年10月更新:使用Node v8(自v8.3左右)以来,它具有对象传播构造:

> var d = { a:undefined, b:2, c:0, d:undefined,
    e: null, f: -0.0, s: "", t: false, inf: +Infinity, nan: NaN };
undefined
> Object.entries(d)
    .filter(([ k, v ]) => (v != null))
    .reduce((acc, [k, v]) => ({...acc, [k]: v}), {})
{ b: 2, c: 0, f: -0, s: '', t: false, inf: Infinity, nan: NaN }

或仅在一个减少内:

> Object.entries(d)
   .reduce((acc, [k, v]) => (v==null ? acc : {...acc, [k]: v}), {})
{ b: 2, c: 0, f: -0, s: '', t: false, inf: Infinity, nan: NaN }

更新:有人想要递归吗?也不难,只需要对isObject进行额外检查,然后递归调用自身即可:

> function isObject(o) {
    return Object.prototype.toString.call(o) === "[object Object]"; }
undefined
> function dropNullUndefined(d) {
    return Object.entries(d)
      .reduce((acc, [k, v]) => (
        v == null ? acc :
         {...acc, [k]: (isObject(v) ? dropNullUndefined(v) : v) }
      ), {});
  }
> dropNullUndefined({a: 3, b:null})
{ a: 3 }
> dropNullUndefined({a: 3, b:null, c: { d: 0, e: undefined }})
{ a: 3, c: { d: 0 } }

我的结论是:如果纯Javascript可以做到,那么我将避免任何第三方库依赖项:


您可以使用Object.fromEntries来避免使用reduce:Object.fromEntries(Object.entries(d).filter(([k,v])=>(v!= null)))
ppierre

5

由于您中的某些人可能已经想到了 专门删除的问题undefined,因此可以使用:

  • Lodash方法的组合

    _.omitBy(object, _.isUndefined)
  • rundef包,其中仅删除undefined属性

    rundef(object)

如果您需要递归删除undefined属性,则该rundef软件包还提供了一个recursive选项。

rundef(object, false, true);

有关更多详细信息,请参见文档



3

考虑到undefined == null我们可以这样写:

let collection = {
  a: undefined,
  b: 2,
  c: 4,
  d: null,
}

console.log(_.omit(collection, it => it == null))
// -> { b: 2, c: 4 }

JSBin示例


1
回顾这个...不知道为什么,但是这次我不得不使用_.omitBy ... json = _.omitBy(json,(it)=>它== null);
danday74 '16



1

使用lodash(或下划线),您可以

var my_object = { a:undefined, b:2, c:4, d:undefined, e:null };

var passedKeys = _.reject(Object.keys(my_object), function(key){ return _.isUndefined(my_object[key]) || _.isNull(my_object[key]) })

newObject = {};
_.each(passedKeys, function(key){
    newObject[key] = my_object[key];
});

否则,使用香草JavaScript,您可以

var my_object = { a:undefined, b:2, c:4, d:undefined };
var new_object = {};

Object.keys(my_object).forEach(function(key){
    if (typeof my_object[key] != 'undefined' && my_object[key]!=null){
        new_object[key] = my_object[key];
    }
});

不要使用虚假测试,因为不仅会拒绝“ undefined”或“ null”,还会出现其他虚假值,例如“ false”,“ 0”,空字符串,{}。因此,为了使其简单易懂,我选择使用上面编码的显式比较。


1
但是,这不是递归的
user3743222

1

要忽略所有错误值,保留布尔基元,此解决方案会有所帮助。

_.omitBy(fields, v => (_.isBoolean(v)||_.isFinite(v)) ? false : _.isEmpty(v));

let fields = {
str: 'CAD',
numberStr: '123',
number  : 123,
boolStrT: 'true',
boolStrF: 'false',
boolFalse : false,
boolTrue  : true,
undef: undefined,
nul: null,
emptyStr: '',
array: [1,2,3],
emptyArr: []
};

let nobj = _.omitBy(fields, v => (_.isBoolean(v)||_.isFinite(v)) ? false : _.isEmpty(v));

console.log(nobj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>


0
var my_object = { a:undefined, b:2, c:4, d:undefined };

var newObject = _.reject(my_collection, function(val){ return _.isUndefined(val) })

//--> newCollection = { b: 2, c: 4 }

1
_.reject将输入视为数组(它仅考虑值,不考虑键),而不是JSON。结果newObject是[2,4]而不是{b:2,c:4}。此外,它不会拒绝“空”键。
TaoPR

0

我将使用下划线并注意空字符串:

var my_object = { a:undefined, b:2, c:4, d:undefined, k: null, p: false, s: '', z: 0 };

var result =_.omit(my_object, function(value) {
  return _.isUndefined(value) || _.isNull(value) || value === '';
});

console.log(result); //Object {b: 2, c: 4, p: false, z: 0}

jsbin


0

用于深层嵌套的对象和数组。并从字符串和NaN中排除空值

function isBlank(value) {
  return _.isEmpty(value) && !_.isNumber(value) || _.isNaN(value);
}
var removeObjectsWithNull = (obj) => {
  return _(obj).pickBy(_.isObject)
    .mapValues(removeObjectsWithNull)
    .assign(_.omitBy(obj, _.isObject))
    .assign(_.omitBy(obj, _.isArray))
    .omitBy(_.isNil).omitBy(isBlank)
    .value();
}
var obj = {
  teste: undefined,
  nullV: null,
  x: 10,
  name: 'Maria Sophia Moura',
  a: null,
  b: '',
  c: {
    a: [{
      n: 'Gleidson',
      i: 248
    }, {
      t: 'Marta'
    }],
    g: 'Teste',
    eager: {
      p: 'Palavra'
    }
  }
}
removeObjectsWithNull(obj)

结果:

{
   "c": {
      "a": [
         {
            "n": "Gleidson",
            "i": 248
         },
         {
            "t": "Marta"
         }
      ],
      "g": "Teste",
      "eager": {
         "p": "Palavra"
      }
   },
   "x": 10,
   "name": "Maria Sophia Moura"
}


0

对于那些想要从对象数组中删除并使用lodash的人来说,可以执行以下操作:


 const objects = [{ a: 'string', b: false, c: 'string', d: undefined }]
 const result = objects.map(({ a, b, c, d }) => _.pickBy({ a,b,c,d }, _.identity))

 // [{ a: 'string', c: 'string' }]

注意:如果不想,您不必破坏。

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.