Como remover valores indefinidos e nulos de um objeto usando o lodash?

172

Eu tenho um objeto Javascript como:

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

Como remover todas as propriedades indefinidas? Atributos falsos devem permanecer.

JLavoie
fonte

Respostas:

195

Se você deseja remover todos os valores de falsey , a maneira mais compacta é:

Para o Lodash 4.xe 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
fonte
63
Observe que, no lodash 4, isso deve ser o seguinte:_.pickBy(obj, _.identity);
Tom Spencer
30
Observe que esse método também removerá o valor falso.
ilimitado
12
Tenha cuidado, isso removerá a propriedade booleana que tem falsevalor
Sai Ram
6
Além de remover false, também remove atributos com 0 e '' como valor ... não é uma boa ideia.
Federico Budassi 19/07/19
4
Esta resposta não é correta, pois também remove valores falsos. Verifique minha resposta abaixo.
Tiago Bértolo 15/03/19
224

Você pode simplesmente encadear _.omit()com _.isUndefinede _.isNullcomposições e obter o resultado com uma avaliação lenta.

Demo

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

Atualização 14 de março de 2016 :

Conforme mencionado por dylants na seção de comentários, você deve usar a _.omitBy()função, pois ela usa um predicado em vez de uma propriedade. Você deve usar isso na versão lodash 4.0.0e acima.

DEMO

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

Atualização 1 de junho de 2016 :

Como comentado por Max Truxa , o lodash já forneceu uma alternativa _.isNil, que verifica os dois nulle undefined:

var result = _.omitBy(my_object, _.isNil);
ryeballar
fonte
7
Aqueles que estão usando versões mais recentes do lodash devem usar a omitByfunção em vez de omit. Então_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants
31
Desde o lodash 4.0.0, você pode usar em _.isNilvez de encadear _.isUndefinede _.isNull. Isso o torna ainda mais curto:var result = _.omitBy(my_object, _.isNil);
Max Truxa
@ MaxTruxa, como você o modificaria para verificar se há valores "Nil" recursivamente?
aegyed
1
O omitBydesempenho de Lodash é menos eficiente do que pickBy, portanto, este último deve ser preferido, e a condição na função iterada é revertida. A resposta aceita acima acertou.
Ernesto
1
A pergunta do OP apenas especifica nulle undefinedvalores. O identitypredicado também removerá falsevalores; portanto, se você simplesmente o basear na intenção da pergunta, não vejo problema com a minha resposta. Além disso, se estivermos falando sobre "desempenho", omitBysimplesmente chame pickBycom um identitypredicado negado , por padrão. Portanto, em termos de desempenho, é muito pequeno para ser significativo.
Ryeballar 13/04
38

se você estiver usando lodash, poderá _.compact(array)remover todos os valores falsamente de uma matriz.

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

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

JavaFish
fonte
36
compacto aplica-se a matrizes, mas a questão é de cerca de objectos
guidoman
1
Exceto que eu quero manter 0. Argh, tão perto.
Sammi
2
@ Sammi, você pode usar _.pickBy(object, _.isNumber)nesse caso.
quer
1
Obrigado @Herick. Isso funciona. Eu vou dormir agora.
technophyle
1
@ Technophyle, eu concordo com você (e sou eu quem escreveu esta resposta, ha). Mas estou mantendo essa resposta aqui em cima, porque, no mínimo, resolve os problemas de algumas pessoas.
JavaFish
25

A resposta correta é:

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

Isso resulta em:

{b: 1, d: false}

A alternativa dada aqui por outras pessoas:

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

Também removerá falsevalores que não são desejados aqui.

Tiago Bértolo
fonte
{"a":1,"b":{"a":1,"b":null,"c":undefined}}, a propriedade object.b b, 'c' não será removida
mqliutie 17/10
@mqliutie como esperado.
Tiago Bértolo 17/10/1919
18

Somente:

_.omit(my_object, _.isUndefined)

O exposto acima não leva em consideração os nullvalores, pois estão ausentes do exemplo original e mencionados apenas no assunto, mas deixo-o como é elegante e pode ter seus usos.

Aqui está o exemplo completo, menos conciso, mas mais 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
fonte
8
Observe que isso é para o Lodash v.3. Para a v.4, você precisa usar _.omitBy.
PhiLho
16

Para concluir as outras respostas, no lodash 4, para ignorar apenas indefinido e nulo (E não propriedades como false), você pode usar um predicado em _.pickBy:

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

Exemplo abaixo:

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
fonte
1
Esta é a melhor solução se você não deseja remover 0, '', falsevalores. Além disso, você pode reduzir o retorno de chamada para v => v != null.
SimpleJ
2
Solução simples. Obrigado por isso.
Arjun G Perambra
10

De acordo com os documentos da lodash:

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

Além disso, você pode filtrar todos os nulos

Oleg Koval
fonte
6

Para objetos aninhados profundos, você pode usar meu snippet 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
};
1nstinct
fonte
5

Encontrei um problema semelhante ao remover undefinedde um objeto (profundamente) e descobri que, se você estiver bem em converter seu objeto antigo simples e usar JSON, uma função auxiliar rápida e suja seria semelhante a esta:

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

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

"... Se indefinido, uma função ou um símbolo for encontrado durante a conversão, ele será omitido (quando encontrado em um objeto) ou censurado para nulo (quando encontrado em uma matriz)."

Jerome
fonte
5

com JavaScript puro: (embora Object.entries seja ES7, Object.assign é ES6; mas o ES5 equivalente usa Object.keys apenas também deve ser possível); também observe v != nullverificações nulas e indefinidas;

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

Edit: esta abaixo é a versão apenas com ES5 Object.keys: mas geralmente com ES7 no nó v8 é bastante agradável ;-)

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

Atualização em outubro de 2017 : com o Node v8 (desde a v8.3 ou mais) agora ele tem a construção de propagação de objeto:

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

ou em apenas uma redução:

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

Atualização: alguém quer recursivo? também não é tão difícil, basta uma verificação adicional de isObject e chamar-se recursivamente:

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

minha conclusão: se o Javascript puro puder fazer, eu evitaria quaisquer dependências da biblioteca de terceiros:

user5672998
fonte
Você pode usar Object.fromEntries para evitar o uso de reduzir: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! =
Null
5

Como alguns de vocês podem ter chegado à pergunta que quer apenas remover especificamente undefined, você pode usar:

  • uma combinação dos métodos Lodash

    _.omitBy(object, _.isUndefined)
  • o rundefpacote, que remove apenas undefinedpropriedades

    rundef(object)

Se você precisar remover propriedades recursivamenteundefined , o rundefpacote também terá uma recursiveopção.

rundef(object, false, true);

Veja a documentação para mais detalhes.

d4nyll
fonte
3

Aqui está a abordagem lodash que eu adotaria:

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

A função pairs () transforma o objeto de entrada em uma matriz de matrizes de chave / valor. Você faz isso para que seja mais fácil usar rejeitar () para eliminar undefinede nullvalores. Depois, você fica com pares que não foram rejeitados e são inseridos para zipObject () , que reconstrói seu objeto para você.

Adam Boduch
fonte
3

Levando em conta que undefined == nullpodemos escrever da seguinte maneira:

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

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

Exemplo de JSBin

Andrejs
fonte
1
revisitando isso ... não sei por que, mas desta vez eu tive que usar _.omitBy ... json = _.omitBy (json, (it) => it == null);
danday74
2

pickBy usa identidade por padrão:

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
fonte
Gosto desta versão mais curta da resposta do @ Tx3. Funciona bem!
Jordan
2

Maneira mais curta (lodash v4):

_.pickBy(my_object)
Vasyl Boroviak
fonte
1

Com lodash (ou sublinhado), você pode fazer

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

Caso contrário, com JavaScript vanilla, você pode fazer

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

Não usar um teste de falsey, porque não apenas "indefinido" ou "nulo" será rejeitado , também há outro valor de falsey como "false", "0", string vazia, {}. Assim, apenas para torná-lo simples e compreensível, optei por usar a comparação explícita, como codificado acima.

TaoPR
fonte
1
embora isso não seja recursivo #
user3743222 16/16/16
1

Para omitir todos os valores de falsey , mas manter os primitivos booleanos que esta solução ajuda.

_.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
fonte
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
fonte
1
_.reject trata a entrada como matriz (ela apenas contabiliza os valores, não as chaves), não um JSON. O newObject resultante é [2,4] e não {b: 2, c: 4}. Além disso, ele não rejeita a chave "nula".
TaoPR
0

Eu usaria sublinhado e cuidaria de cadeias vazias também:

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
fonte
0

Para objetos e matrizes aninhados profundos. e excluir valores vazios da string e do 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
fonte
0

Para aqueles que estão chegando aqui procurando remover de uma matriz de objetos e usando o lodash, podem fazer algo assim:


 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: Você não precisa destruir se não quiser.

User_coder
fonte