Wie entferne ich undefinierte und Nullwerte mit lodash aus einem Objekt?

172

Ich habe ein Javascript-Objekt wie:

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

Wie entferne ich alle undefinierten Eigenschaften? Falsche Attribute sollten bleiben.

JLavoie
quelle

Antworten:

195

Wenn Sie alle Falsey- Werte entfernen möchten , ist der kompakteste Weg:

Für Lodash 4.x und höher :

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

Für Legacy- Lodash 3.x:

_.pick(obj, _.identity);

_.pick({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}
Tx3
quelle
63
Bitte beachten Sie, dass dies in Lodge 4 sein sollte_.pickBy(obj, _.identity);
Tom Spencer
30
Bitte beachten Sie, dass diese Methode auch falsche Werte entfernt.
unbegrenzt
12
Seien Sie vorsichtig, dies wird boolesche Eigenschaft mit falseWert entfernen
Sai Ram
6
Neben dem Entfernen von false werden auch Attribute mit 0 und '' als Wert entfernt ... keine gute Idee.
Federico Budassi
4
Diese Antwort ist nicht korrekt, da sie auch falsche Werte entfernt. Überprüfen Sie meine Antwort unten.
Tiago Bértolo
224

Sie können einfach _.omit()mit _.isUndefinedund _.isNullKompositionen verketten und das Ergebnis mit einer verzögerten Bewertung erhalten.

Demo

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

Update 14. März 2016 :

Wie von Dylants im Kommentarbereich erwähnt, sollten Sie die _.omitBy()Funktion verwenden, da sie ein Prädikat anstelle einer Eigenschaft verwendet. Sie sollten dies für die lodash-Version 4.0.0und höher verwenden.

DEMO

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

Update 1. Juni 2016 :

Wie von Max Truxa kommentiert , bot lodash bereits eine Alternative _.isNil, die sowohl prüft nullals auch undefined:

var result = _.omitBy(my_object, _.isNil);
Roggenballar
quelle
7
Diejenigen, die neuere Versionen von lodash verwenden, sollten die omitByFunktion anstelle von verwenden omit. So_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants
31
Seit lodash 4.0.0 können Sie _.isNilanstelle von Verkettung _.isUndefinedund verwenden _.isNull. Dies macht es noch kürzer:var result = _.omitBy(my_object, _.isNil);
Max Truxa
@ MaxTruxa Wie würden Sie es ändern, um rekursiv nach "Null" -Werten zu suchen?
Uhr
1
Lodashs omitByist weniger performant als pickBy, daher sollte letzteres bevorzugt und die Bedingung in der Iteratee-Funktion umgekehrt werden. Die oben akzeptierte Antwort hat das richtig verstanden.
Ernesto
1
Die Frage des OP nur angegeben nullund undefinedWerte. Das identityPrädikat entfernt auch falseWerte. Wenn Sie es also einfach auf der Absicht der Frage basieren, sehe ich kein Problem mit meiner Antwort. Wenn es um "Leistung" geht, rufen Sie standardmäßig omitByeinfach pickBymit einem negierten identityPrädikat auf. In Bezug auf die Leistung ist es also zu klein, um signifikant zu sein.
Roggenballar
38

Wenn Sie lodash verwenden, können Sie _.compact(array)alle falschen Werte aus einem Array entfernen.

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

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

JavaFish
quelle
36
Kompakt gilt für Arrays, aber die Frage betrifft Objekte
Guidoman
1
Außer ich möchte 0 behalten. Argh, so nah.
Sammi
2
@Sammi, können Sie _.pickBy(object, _.isNumber)in diesem Fall verwenden.
John Rix
1
Danke @Herick. Das funktioniert. Ich werde jetzt schlafen gehen.
Technophyle
1
@technophyle, ich stimme dir zu (und ich bin derjenige, der diese Antwort geschrieben hat, ha). Aber ich halte diese Antwort hier oben, weil sie zumindest die Probleme einiger Menschen löst .
JavaFish
24

Die richtige Antwort ist:

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

Das ergibt:

{b: 1, d: false}

Die hier von anderen Leuten gegebene Alternative:

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

Entfernt auch falseWerte, die hier nicht erwünscht sind.

Tiago Bértolo
quelle
{"a":1,"b":{"a":1,"b":null,"c":undefined}}, object.b Eigenschaft b, 'c' wird nicht entfernt
mqliutie
@mqliutie wie erwartet.
Tiago Bértolo
17

Gerade:

_.omit(my_object, _.isUndefined)

Das Obige berücksichtigt keine nullWerte, da sie im ursprünglichen Beispiel fehlen und nur im Betreff erwähnt werden, aber ich lasse es, da es elegant ist und möglicherweise seine Verwendung hat.

Hier ist das vollständige Beispiel, weniger präzise, ​​aber vollständiger.

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
quelle
7
Beachten Sie, dass dies für Lodash v.3 gilt. Für v.4 müssen Sie verwenden _.omitBy.
PhiLho
16

Um die anderen Antworten zu vervollständigen, können Sie in lodash 4, um nur undefiniert und null (und nicht Eigenschaften wie false) zu ignorieren , ein Prädikat verwenden in _.pickBy:

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

Beispiel unten:

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
quelle
1
Dies ist die beste Lösung , wenn Sie nicht wollen , zu entfernen 0, '', falseWerte. Sie können den Rückruf auch auf verkürzen v => v != null.
SimpleJ
2
Einfache Lösung. Danke dafür.
Arjun G Perambra
10

Laut lodash docs:

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

Sie können auch alle Nullen herausfiltern

Oleg Koval
quelle
6

Für tief verschachtelte Objekte können Sie mein Snippet für lodash> 4 verwenden

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
quelle
5

Ich bin auf ein ähnliches Problem beim Entfernen undefinedvon einem Objekt (tiefgreifend) gestoßen und habe festgestellt, dass eine schnelle und schmutzige Hilfsfunktion folgendermaßen aussehen würde, wenn Sie Ihr einfaches altes Objekt konvertieren und JSON verwenden können:

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

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

"... Wenn eine undefinierte Funktion oder ein Symbol während der Konvertierung angetroffen wird, wird es entweder weggelassen (wenn es in einem Objekt gefunden wird) oder auf null zensiert (wenn es in einem Array gefunden wird)."

Jerome
quelle
5

mit reinem JavaScript: (obwohl Object.entries ES7 ist, ist Object.assign ES6; aber äquivalent ES5 verwendet nur Object.keys sollte auch machbar sein); Beachten Sie auch die v != nullÜberprüfungen auf null und undefiniert.

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

Bearbeiten: Dies unten ist die Version nur mit ES5 Object.keys: aber im Allgemeinen mit ES7 in Node v8 ist ziemlich viel Spaß ;-)

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

Update im Oktober 2017 : Mit Node v8 (seit v8.3 oder so) hat es jetzt ein Objektverbreitungskonstrukt:

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

oder nur innerhalb einer reduzieren:

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

Update: will jemand rekursiv? ist auch nicht so schwer, brauche nur eine zusätzliche Überprüfung von isObject und rufe sich rekursiv auf:

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

Mein Fazit: Wenn reines Javascript dies kann, würde ich jegliche Bibliotheksabhängigkeiten von Drittanbietern vermeiden:

user5672998
quelle
5

Da einige von Ihnen möglicherweise zu der Frage gekommen sind, nur gezielt zu entfernen undefined, können Sie Folgendes verwenden:

  • eine Kombination von Lodash-Methoden

    _.omitBy(object, _.isUndefined)
  • das rundefPaket, das nur undefinedEigenschaften entfernt

    rundef(object)

Wenn Sie Eigenschaften rekursiv entfernen müssen undefined, verfügt das rundefPaket auch über eine recursiveOption.

rundef(object, false, true);

Weitere Informationen finden Sie in der Dokumentation .

d4nyll
quelle
3

Hier ist der Lodash-Ansatz, den ich wählen würde:

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

Die Funktion pair () verwandelt das Eingabeobjekt in ein Array von Schlüssel / Wert-Arrays. Sie tun dies, damit es einfacher ist, Reject () zum Eliminieren undefinedund nullWerte zu verwenden. Danach bleiben Paare übrig, die nicht abgelehnt wurden, und diese werden für zipObject () eingegeben , das Ihr Objekt für Sie rekonstruiert.

Adam Boduch
quelle
3

Unter Berücksichtigung, dass undefined == nullwir wie folgt schreiben können:

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

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

JSBin Beispiel

Andrejs
quelle
1
Wiederholung dieses ... nicht sicher warum, aber dieses Mal musste ich _.omitBy verwenden ... json = _.omitBy (json, (it) => it == null);
danday74
2

pickBy verwendet standardmäßig Identität :

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
quelle
Ich mag diese kürzere Version von @ Tx3s Antwort. Funktioniert gut!
Jordanien
2

Kürzester Weg (lodash v4):

_.pickBy(my_object)
Vasyl Boroviak
quelle
1

Mit lodash (oder Unterstrich) können Sie tun

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

Andernfalls können Sie mit Vanille-JavaScript tun

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

Verwenden Sie keinen Falsey-Test, da nicht nur "undefined" oder "null" abgelehnt wird, sondern auch andere Falsey-Werte wie "false", "0", leere Zeichenfolge, {}. Um es einfach und verständlich zu machen, habe ich mich für den expliziten Vergleich entschieden, wie oben codiert.

TaoPR
quelle
1
Dies ist jedoch nicht rekursiv
user3743222
1

Um alle Falsey- Werte wegzulassen , aber die booleschen Grundelemente beizubehalten , hilft diese Lösung.

_.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
quelle
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
quelle
1
_.reject behandelt Eingaben als Array (es berücksichtigt nur die Werte, keine Schlüssel), nicht als JSON. Das resultierende neue Objekt ist [2,4] nicht {b: 2, c: 4}. Außerdem wird der "Null" -Schlüssel nicht abgelehnt.
TaoPR
0

Ich würde Unterstrich verwenden und mich auch um leere Zeichenfolgen kümmern:

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

Für tief verschachtelte Objekte und Arrays. und leere Werte von String und NaN ausschließen

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)

Ergebnis:

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

Für diejenigen unter Ihnen, die hierher kommen, um aus einer Reihe von Objekten zu entfernen und lodash zu verwenden, können Sie Folgendes tun:


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

Hinweis: Sie müssen nicht zerstören, wenn Sie nicht möchten.

User_coder
quelle