¿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.

JLavoie
fuente

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}
Tx3
fuente
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);
ryeballar
fuente
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

JavaFish
fuente
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í.

Tiago Bértolo
fuente
{"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); }));
PhiLho
fuente
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>

nSimonFR
fuente
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

Oleg Koval
fuente
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
};
1 instinto
fuente
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)".

Jerome
fuente
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:

usuario5672998
fuente
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.

d4nyll
fuente
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.

Adam Boduch
fuente
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

Andrejs
fuente
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
2

pickBy usa identidad por defecto:

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
fuente
Me gusta esta versión más corta de la respuesta de @ Tx3. Funciona muy bien!
Jordania
2

El camino más corto (lodash v4):

_.pickBy(my_object)
Vasyl Boroviak
fuente
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.

TaoPR
fuente
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/[email protected]/lodash.min.js"></script>

Marcio LSA
fuente
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 }
JLavoie
fuente
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 .

mrgoos
fuente
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"
}
Gleidosn
fuente
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.

User_coder
fuente