¿Cómo eliminar valores indefinidos y nulos de un objeto usando lodash?


173

Tengo un objeto Javascript como:

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

¿Cómo eliminar todas las propiedades indefinidas? Los atributos falsos deberían permanecer.

Respuestas:


195

Si desea eliminar todos los valores de falsey , la forma más compacta es:

Para Lodash 4.xy posterior :

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

Para legado Lodash 3.x:

_.pick(obj, _.identity);

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

63
Tenga en cuenta que en lodash 4 esto debería ser_.pickBy(obj, _.identity);
Tom Spencer

30
Tenga en cuenta que este método también eliminará el valor falso.
ilimitado

12
Tenga cuidado, esto eliminará la propiedad booleana que tiene falseValu
Sai Ram

66
Además de eliminar false, también eliminará los atributos con 0 y '' como valor ... no es una buena idea.
Federico Budassi

44
Esta respuesta no es correcta ya que también elimina los valores falsos. Mira mi respuesta a continuación.
Tiago Bértolo

225

Simplemente puede encadenar _.omit()con _.isUndefinedy _.isNullcomposiciones, y obtener el resultado con una evaluación perezosa.

Manifestación

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

Actualización 14 de marzo de 2016 :

Como lo mencionan los dylants en la sección de comentarios, debe usar la _.omitBy()función ya que usa un predicado en lugar de una propiedad. Debe usar esto para la versión lodash 4.0.0y superior.

MANIFESTACIÓN

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

Actualización 1 de junio de 2016 :

Como comentó Max Truxa , lodash ya proporcionó una alternativa _.isNil, que verifica ambos nully undefined:

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

77
Aquellos que usan versiones más recientes de lodash deben usar la omitByfunción en lugar de omit. So_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants

31
Desde lodash 4.0.0 puede usar en _.isNillugar de encadenar _.isUndefinedy _.isNull. Esto lo hace aún más corto:var result = _.omitBy(my_object, _.isNil);
Max Truxa

@MaxTruxa, ¿cómo lo modificaría para verificar los valores "nulos" de forma recursiva?
aegyed

1
Lodash omitBytiene menos rendimiento que pickBy, por lo que se debe preferir este último, y la condición en la función iterada se invierte. La respuesta aceptada arriba acertó.
Ernesto

1
La pregunta del OP solo especifica nully undefinedvalores. El identitypredicado también eliminará falsevalores, por lo que si simplemente lo basó en la intención de la pregunta, entonces no veo un problema con mi respuesta. Además, si estamos hablando de "rendimiento", omitBysimplemente llama pickBycon un identitypredicado negado , por defecto. Entonces, en términos de rendimiento, es demasiado pequeño para ser significativo.
ryeballar

38

si está usando lodash, puede usar _.compact(array)para eliminar todos los valores falsos de una matriz.

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

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


36
compact se aplica a las matrices, pero la pregunta es sobre los objetos
guidoman

1
Excepto que quiero mantener 0. Argh, muy cerca.
Sammi

2
@ Sammi, puedes usar _.pickBy(object, _.isNumber)en ese caso.
John Rix

1
Gracias @Herick. Eso funciona. Yo ire a dormir ahora.
technophyle

1
@technophyle, estoy de acuerdo contigo (y yo fui quien escribió esta respuesta, ja). Pero mantengo esta respuesta aquí porque, como mínimo, resuelve los problemas de algunas personas.
JavaFish

26

La respuesta correcta es:

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

Eso da como resultado:

{b: 1, d: false}

La alternativa dada aquí por otras personas:

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

Eliminará también los falsevalores que no se desean aquí.


{"a":1,"b":{"a":1,"b":null,"c":undefined}}, propiedad object.b b, 'c' no se eliminará
mqliutie

@mqliutie como se esperaba.
Tiago Bértolo

18

Sólo:

_.omit(my_object, _.isUndefined)

Lo anterior no tiene en cuenta los nullvalores, ya que faltan en el ejemplo original y se mencionan solo en el tema, pero lo dejo ya que es elegante y podría tener sus usos.

Aquí está el ejemplo completo, menos conciso, pero más completo.

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
Tenga en cuenta que esto es para Lodash v.3. Para v.4, tienes que usar _.omitBy.
PhiLho

16

Para completar las otras respuestas, en lodash 4 para ignorar solo indefinido y nulo (y no propiedades como false) puede usar un predicado en _.pickBy:

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

Ejemplo a continuación:

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
Esta es la mejor solución si no se desea eliminar 0, '', falsevalores. También puede acortar la devolución de llamada a v => v != null.
SimpleJ

2
Solución simple. Gracias por esto.
Arjun G Perambra

10

De acuerdo con lodash docs:

_.compact(_.map(array, fn))

También puedes filtrar todos los nulos


6

Para objetos anidados profundos, puede usar mi fragmento para 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

Encontré un problema similar con la eliminación undefinedde un objeto (profundamente), y descubrí que si está bien para convertir su objeto antiguo simple y usar JSON, una función auxiliar rápida y sucia se vería así:

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

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

"... Si no se define, se encuentra una función o un símbolo durante la conversión, se omite (cuando se encuentra en un objeto) o se censura a nulo (cuando se encuentra en una matriz)".


5

con JavaScript puro: (aunque Object.entries es ES7, Object.assign es ES6; pero el ES5 equivalente usa Object.keys solo debería ser factible); también observe las v != nullcomprobaciones tanto para nulo como para indefinido;

> 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 }

Editar: esta a continuación es la versión con ES5 Object.keys solamente: pero en general con ES7 en el Nodo v8 es bastante agradable ;-)

> 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 }

Actualización en octubre de 2017 : con el Nodo v8 (desde v8.3 más o menos) ahora tiene una construcción de difusión de objetos:

> 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 }

o dentro de una reducción solamente:

> 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 }

Actualización: alguien quiere recursivo? tampoco es tan difícil, solo necesito una verificación adicional de isObject y recursivamente se llama a sí mismo:

> 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 } }

Mi conclusión: si JavaScript puro puede hacer, evitaría las dependencias de la biblioteca de terceros:


Puede usar Object.fromEntries para evitar usar reduce: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! =
Null

5

Dado que algunos de ustedes podrían haber llegado a la pregunta buscando eliminar específicamente solo undefined , pueden usar:

  • una combinación de métodos de Lodash

    _.omitBy(object, _.isUndefined)
  • el rundefpaquete, que elimina solo las undefinedpropiedades

    rundef(object)

Si necesita eliminar propiedades de forma recursivaundefined , el rundefpaquete también tiene una recursiveopción.

rundef(object, false, true);

Consulte la documentación para más detalles.


3

Aquí está el enfoque lodash que tomaría:

_(my_object)
    .pairs()
    .reject(function(item) {
        return _.isUndefined(item[1]) ||
            _.isNull(item[1]);
    })
    .zipObject()
    .value()

La función pares () convierte el objeto de entrada en una matriz de matrices de clave / valor. Haces esto para que sea más fácil usar rechazar () para eliminar undefinedy nullvalores. Después, te quedan pares que no fueron rechazados, y estos son datos de entrada para zipObject () , que reconstruye tu objeto por ti.


3

Teniendo en cuenta que undefined == nullpodemos escribir de la siguiente manera:

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

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

JSBin ejemplo


1
volviendo a visitar esto ... no estoy seguro de por qué, pero esta vez tuve que usar _.omitBy ... json = _.omitBy (json, (it) => it == null);
danday74



1

Con lodash (o guión bajo) puede hacer

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];
});

De lo contrario, con JavaScript vainilla, puedes hacer

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];
    }
});

No usar una prueba de falsey, porque no solo se rechazará "indefinido" o "nulo" , sino que también hay otro valor de falsey como "falso", "0", cadena vacía, {}. Por lo tanto, solo para hacerlo simple y comprensible, opté por usar una comparación explícita como se codificó anteriormente.


1
sin embargo
user3743222

1

Para omitir todos los valores de falsey pero mantener las primitivas booleanas, esta solución ayuda.

_.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 trata la entrada como una matriz (solo tiene en cuenta los valores, no las claves), no un JSON. El nuevo objeto resultante es [2,4] no {b: 2, c: 4}. Además, no rechaza la clave "nula".
TaoPR

0

Usaría guión bajo y me ocuparía de las cadenas vacías también:

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

Para objetos anidados profundos y matrices. y excluir valores vacíos de cadena y 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)

resultado:

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


0

Para aquellos de ustedes que están aquí buscando eliminar de una matriz de objetos y usar lodash, pueden hacer algo como esto:


 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' }]

Nota: No tienes que destruir si no quieres.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.