Comment supprimer les valeurs non définies et nulles d'un objet à l'aide de lodash?

173

J'ai un objet Javascript comme:

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

Comment supprimer toutes les propriétés non définies? Les faux attributs doivent rester.

JLavoie
la source

Réponses:

195

Si vous souhaitez supprimer toutes les valeurs falsey , le moyen le plus compact est:

Pour Lodash 4.x et versions ultérieures :

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

Pour l' ancien Lodash 3.x:

_.pick(obj, _.identity);

_.pick({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}
Tx3
la source
63
Veuillez noter que dans lodash 4, cela devrait être_.pickBy(obj, _.identity);
Tom Spencer
30
Veuillez noter que cette méthode supprimera également les fausses valeurs.
illimité
12
Attention, cela supprimera la propriété booléenne ayant falseValu
Sai Ram
6
En plus de supprimer false, cela supprimera également les attributs avec 0 et '' comme valeur ... ce n'est pas une bonne idée.
Federico Budassi
4
Cette réponse n'est pas correcte car elle supprime également les fausses valeurs. Vérifiez ma réponse ci-dessous.
Tiago Bértolo
225

Vous pouvez simplement enchaîner _.omit()avec _.isUndefinedet _.isNullcompositions, et obtenir le résultat avec l' évaluation paresseuse.

Démo

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

Mise à jour du 14 mars 2016 :

Comme mentionné par les dylants dans la section des commentaires, vous devez utiliser la _.omitBy()fonction car elle utilise un prédicat au lieu d'une propriété. Vous devriez l'utiliser pour la version lodash 4.0.0et au-dessus.

DEMO

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

Mise à jour du 1er juin 2016 :

Comme l'a commenté Max Truxa , lodash offrait déjà une alternative _.isNil, qui vérifie à la fois nullet undefined:

var result = _.omitBy(my_object, _.isNil);
seigle
la source
7
Ceux qui utilisent des versions plus récentes de lodash devraient utiliser la omitByfonction à la place de omit. So_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants
31
Depuis lodash 4.0.0, vous pouvez utiliser _.isNilau lieu de chaîner _.isUndefinedet _.isNull. Cela le rend encore plus court:var result = _.omitBy(my_object, _.isNil);
Max Truxa
@MaxTruxa comment le modifieriez-vous pour vérifier les valeurs "Nil" de manière récursive?
aegyed
1
Lodash omitByest moins performant que pickBy, donc ce dernier doit être préféré, et la condition de la fonction iteratee inversée. La réponse acceptée ci-dessus a raison.
Ernesto
1
La question de l'OP seulement spécifiée nullet undefinedvaleurs. Le identityprédicat supprimera également des falsevaleurs, donc si vous le basez simplement sur l'intention de la question, je ne vois pas de problème avec ma réponse. De plus, si nous parlons de «performances», il omitBysuffit d'appeler pickByavec un identityprédicat annulé , par défaut. Donc, en termes de performances, c'est trop petit pour être significatif.
ryeballar
38

si vous utilisez lodash, vous pouvez utiliser _.compact(array)pour supprimer toutes les fausses valeurs d'un tableau.

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

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

JavaFish
la source
36
compact s'applique aux tableaux mais la question concerne les objets
guidoman
1
Sauf que je veux garder 0. Argh, si proche.
Sammi
2
@Sammi, vous pouvez utiliser _.pickBy(object, _.isNumber)dans ce cas.
John Rix
1
Merci @Herick. Ça marche. Je vais aller dormir maintenant.
technophyle
1
@technophyle, je suis d'accord avec vous (et c'est moi qui ai écrit cette réponse, ha). Mais je garde cette réponse ici parce que cela résout au moins les problèmes de certaines personnes.
JavaFish
26

La bonne réponse est:

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

Cela se traduit par:

{b: 1, d: false}

L'alternative donnée ici par d'autres personnes:

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

Supprime également les falsevaleurs qui ne sont pas souhaitées ici.

Tiago Bértolo
la source
{"a":1,"b":{"a":1,"b":null,"c":undefined}}, propriété object.b b, 'c' ne sera pas supprimé
mqliutie
@mqliutie comme prévu.
Tiago Bértolo
18

Juste:

_.omit(my_object, _.isUndefined)

Ce qui précède ne prend pas en compte les nullvaleurs, car elles sont absentes de l'exemple d'origine et mentionnées uniquement dans le sujet, mais je la laisse car elle est élégante et pourrait avoir ses utilisations.

Voici l'exemple complet, moins concis, mais plus complet.

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
la source
8
Notez que c'est pour Lodash v.3. Pour la v.4, vous devez utiliser _.omitBy.
PhiLho
16

Pour compléter les autres réponses, dans lodash 4 pour ignorer uniquement indéfini et nul (et pas des propriétés comme false), vous pouvez utiliser un prédicat dans _.pickBy:

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

Exemple ci-dessous:

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
la source
1
Ceci est la meilleure solution si vous ne voulez pas supprimer 0, '', les falsevaleurs. Vous pouvez également raccourcir le rappel en v => v != null.
SimpleJ
2
Solution simple. Merci pour ça.
Arjun G Perambra
10

Selon les documents de lodash:

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

Vous pouvez également filtrer toutes les valeurs nulles

Oleg Koval
la source
6

Pour un objet imbriqué profond, vous pouvez utiliser mon extrait de code pour 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
la source
5

J'ai rencontré un problème similaire avec la suppression undefinedd'un objet (profondément), et j'ai trouvé que si vous êtes d'accord pour convertir votre ancien objet ordinaire et utiliser JSON, une fonction d'aide rapide et sale ressemblerait à ceci:

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 indéfini, une fonction ou un symbole est rencontré lors de la conversion, il est soit omis (lorsqu'il est trouvé dans un objet), soit censuré à null (lorsqu'il est trouvé dans un tableau)."

Jérôme
la source
5

avec du JavaScript pur: (bien qu'Object.entries soit ES7, Object.assign est ES6; mais l'équivalent ES5 utilise uniquement Object.keys devrait également être faisable); notez également les v != nullvérifications de null et d'indéfini;

> 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: ceci ci-dessous est la version avec ES5 Object.keys uniquement: mais généralement avec ES7 dans Node v8 est plutôt agréable ;-)

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

Mise à jour d'octobre 2017 : avec Node v8 (depuis la v8.3 environ), il a maintenant une construction de propagation d'objets:

> 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 dans une seule réduction:

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

Mise à jour: quelqu'un veut récursif? n'est pas si difficile non plus, il suffit d'une vérification supplémentaire de isObject et de s'appeler récursivement:

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

ma conclusion: si Javascript pur peut le faire, j'éviterais toute dépendance de bibliothèque tierce:

user5672998
la source
Vous pouvez utiliser Object.fromEntries pour éviter d'utiliser réduire: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! = Null)))
ppierre
5

Étant donné que certains d'entre vous sont peut-être arrivés à la question en cherchant à supprimer spécifiquement uniquement undefined , vous pouvez utiliser:

  • une combinaison de méthodes Lodash

    _.omitBy(object, _.isUndefined)
  • le rundefpackage, qui supprime uniquement les undefinedpropriétés

    rundef(object)

Si vous devez supprimer des propriétés de manière récursiveundefined , le rundefpackage a également une recursiveoption.

rundef(object, false, true);

Consultez la documentation pour plus de détails.

d4nyll
la source
3

Voici l'approche lodash que je prendrais:

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

La fonction pairs () transforme l'objet d'entrée en un tableau de tableaux clé / valeur. Vous faites cela pour qu'il soit plus facile d'utiliser rejeter () pour éliminer undefinedet nullvaloriser. Après, vous vous retrouvez avec des paires qui n'ont pas été rejetées, et celles-ci sont entrées pour zipObject () , qui reconstruit votre objet pour vous.

Adam Boduch
la source
3

En tenant compte du fait que undefined == nullnous pouvons écrire comme suit:

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

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

Exemple JSBin

Andrejs
la source
1
revisitant ceci ... je ne sais pas pourquoi mais cette fois j'ai dû utiliser _.omitBy ... json = _.omitBy (json, (it) => it == null);
danday74
2

pickBy utilise l' identité par défaut:

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
la source
J'aime cette version plus courte de la réponse de @ Tx3. Fonctionne bien!
Jordanie
2

Chemin le plus court (lodash v4):

_.pickBy(my_object)
Vasyl Boroviak
la source
1

Avec lodash (ou soulignement) vous pouvez faire

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

Sinon, avec JavaScript vanille, vous pouvez faire

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

Ne pas utiliser un test faux, car non seulement "undefined" ou "null" sera rejeté , il y a aussi d'autres valeurs fausses comme "false", "0", chaîne vide, {}. Ainsi, juste pour le rendre simple et compréhensible, j'ai choisi d'utiliser la comparaison explicite comme codé ci-dessus.

TaoPR
la source
1
ce n'est pas récursif cependant
user3743222
1

Pour omettre toutes les valeurs falsey mais conserver les primitives booléennes, cette solution est utile.

_.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
la source
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
la source
1
_.reject traite l'entrée comme un tableau (il ne prend en compte que les valeurs, pas les clés), pas un JSON. Le newObject résultant est [2,4] et non {b: 2, c: 4}. De plus, il ne rejette pas la clé «nulle».
TaoPR
0

J'utiliserais un trait de soulignement et m'occuperais également des chaînes vides:

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
la source
0

Pour les objets et les tableaux imbriqués en profondeur. et exclure les valeurs vides de la chaîne et de 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)

résultat:

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

Pour ceux d'entre vous qui cherchent à supprimer d'un tableau d'objets et qui utilisent lodash, vous pouvez faire quelque chose comme ceci:


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

Remarque: vous n'avez pas à détruire si vous ne le souhaitez pas.

User_coder
la source