Jak usunąć niezdefiniowane i null wartości z obiektu za pomocą lodash?

172

Mam obiekt JavaScript, taki jak:

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

Jak usunąć wszystkie niezdefiniowane właściwości? Fałszywe atrybuty powinny pozostać.

JLavoie
źródło

Odpowiedzi:

195

Jeśli chcesz usunąć wszystkie wartości falsey, najbardziej zwarty sposób to:

Dla Lodash 4.x i nowszych :

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

W przypadku starszej wersji Lodash 3.x:

_.pick(obj, _.identity);

_.pick({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}
Tx3
źródło
63
Należy pamiętać, że w lodash 4 powinno to być_.pickBy(obj, _.identity);
Tom Spencer
30
Pamiętaj, że ta metoda usunie również wartość fałszywą.
nieograniczony
12
Bądź ostrożny, spowoduje to usunięcie logiczną mienia od falseVALU
Sai Ram
6
Oprócz usunięcia fałszu, usunie również atrybuty z 0 i „” jako wartością ... nie jest to dobry pomysł.
Federico Budassi
4
Ta odpowiedź nie jest poprawna, ponieważ usuwa również fałszywe wartości. Sprawdź moją odpowiedź poniżej.
Tiago Bértolo
224

Można po prostu łańcuch _.omit()z _.isUndefinedi _.isNullkompozycje, a otrzymasz wynik z oceny leniwy.

Próbny

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

Aktualizacja z 14 marca 2016 r . :

Jak wspomnieli dylanci w sekcji komentarzy, powinieneś używać _.omitBy()funkcji, ponieważ używa ona predykatu zamiast właściwości. Powinieneś użyć tego dla wersji lodash 4.0.0i nowszych.

PRÓBNY

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

Aktualizacja z 1 czerwca 2016 r . :

Jak skomentował Max Truxa , lodash dostarczył już alternatywę _.isNil, która sprawdza zarówno, jak nulli undefined:

var result = _.omitBy(my_object, _.isNil);
ryeballar
źródło
7
Ci, którzy używają nowszych wersji lodash, powinni używać omitByfunkcji zamiast omit. A więc_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants
31
Od lodash 4.0.0 możesz używać _.isNilzamiast łańcuchów _.isUndefinedi _.isNull. To czyni go jeszcze krótszym:var result = _.omitBy(my_object, _.isNil);
Max Truxa
@MaxTruxa Jak zmodyfikowałbyś to, aby rekurencyjnie sprawdzać wartości „Nil”?
aegyed
1
Lodash omitByjest mniej wydajny niż pickBy, więc ten drugi powinien być preferowany, a warunek w funkcji iteracyjnej odwrócony. Przyjęta powyżej odpowiedź jest właściwa.
Ernesto
1
Pytanie PO zawierało tylko określone nulli undefinedwartości. identityOrzecznik usunie również falsewartości, więc jeśli po prostu opiera się na pytaniu za intencją wtedy nie widzę problemu z moją odpowiedź. Dodatkowo, jeśli zajmujemy się „wydajnością”, omitBypo prostu domyślnie wywołuje pickByz zanegowanym identitypredykatem. Więc jeśli chodzi o wydajność, jest zbyt mały, aby był znaczący.
ryeballar
38

jeśli używasz lodash, możesz użyć _.compact(array)do usunięcia wszystkich fałszywych wartości z tablicy.

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

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

JavaFish
źródło
36
compact dotyczy tablic, ale pytanie dotyczy obiektów
guidoman,
1
Poza tym, że chcę mieć 0. Ach, tak blisko.
Sammi
2
@Sammi, możesz użyć _.pickBy(object, _.isNumber)w takim przypadku.
John Rix,
1
Dziękuję @Herick. To działa. Pójdę teraz spać.
technophyle
1
@technophyle, zgadzam się z tobą (i to ja napisałem tę odpowiedź, ha). Ale trzymam tę odpowiedź tutaj, ponieważ przynajmniej rozwiązuje ona problemy niektórych ludzi.
JavaFish
25

Poprawna odpowiedź to:

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

Skutkuje to:

{b: 1, d: false}

Alternatywa podana tutaj przez inne osoby:

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

Usunie również falsewartości, które nie są tutaj pożądane.

Tiago Bértolo
źródło
{"a":1,"b":{"a":1,"b":null,"c":undefined}}, object.b b, 'c' nie zostanie usunięty
mqliutie
@mqliutie zgodnie z oczekiwaniami.
Tiago Bértolo
18

Właśnie:

_.omit(my_object, _.isUndefined)

Powyższe nie bierze pod uwagę nullwartości, ponieważ brakuje ich w oryginalnym przykładzie i wspomniane tylko w temacie, ale zostawiam to, ponieważ jest eleganckie i może mieć swoje zastosowania.

Oto kompletny przykład, mniej zwięzły, ale bardziej kompletny.

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
źródło
8
Zwróć uwagę, że dotyczy to Lodash v.3. W przypadku wersji 4 musisz użyć _.omitBy.
PhiLho
16

Aby uzupełnić inne odpowiedzi, w lodash 4, aby zignorować tylko undefined i null (a nie właściwości takie jak false), możesz użyć predykatu w _.pickBy:

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

Przykład poniżej:

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
źródło
1
Jest to najlepsze rozwiązanie, jeśli nie chcesz usuwać 0, '', falsewartości. Możesz także skrócić oddzwanianie do v => v != null.
SimpleJ
2
Proste rozwiązanie. Dziękuję Ci za to.
Arjun G Perambra
10

Według lodash Docs:

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

Możesz także odfiltrować wszystkie wartości null

Oleg Koval
źródło
6

W przypadku głęboko zagnieżdżonych obiektów możesz użyć mojego fragmentu dla 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
źródło
5

Napotkałem podobny problem z usuwaniem undefinedz obiektu (głęboko) i stwierdziłem, że jeśli możesz przekonwertować zwykły stary obiekt i użyć JSON, szybka i brudna funkcja pomocnicza wyglądałaby tak:

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

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

„... Jeśli podczas konwersji napotkana zostanie funkcja lub symbol, który jest niezdefiniowany, jest on albo pomijany (gdy zostanie znaleziony w obiekcie), albo ocenzurowany do wartości null (gdy zostanie znaleziony w tablicy)."

jerome
źródło
5

z czystym JavaScript: (chociaż Object.entries to ES7, Object. assign to ES6; ale odpowiednik ES5 używa tylko Object.keys, powinno być również możliwe); zwróć także uwagę na v != nullsprawdzanie zarówno wartości zerowej, jak i niezdefiniowanej;

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

Edycja: poniżej znajduje się wersja z ES5 Object.keys: ale ogólnie z ES7 w Node v8 jest całkiem przyjemna ;-)

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

Aktualizacja w październiku 2017 r . : w Node v8 (od wersji 8.3 lub podobnej) ma teraz konstrukcję rozprzestrzeniania obiektów:

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

lub tylko w ramach jednej obniżki:

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

Aktualizacja: ktoś chce rekurencyjny? też nie jest to trudne, po prostu potrzebuję dodatkowego sprawdzenia isObject i rekurencyjnie wywołuj siebie:

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

mój wniosek: jeśli wystarczy czysty Javascript, unikałbym wszelkich zależności bibliotek innych firm:

user5672998
źródło
Możesz użyć Object.fromEntries, aby uniknąć korzystania z redukuj: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! = Null)))
ppierre
5

Ponieważ niektórzy z was mogliby dojść do pytania, które dotyczy tylko usunięcia undefined, możesz użyć:

  • połączenie metod Lodash

    _.omitBy(object, _.isUndefined)
  • rundefPakiet, który usuwa tylko undefinedwłaściwości

    rundef(object)

Jeśli chcesz rekurencyjnie usunąć undefinedwłaściwości, rundefpakiet ma również recursiveopcję.

rundef(object, false, true);

Więcej informacji można znaleźć w dokumentacji .

d4nyll
źródło
3

Oto podejście, które obrałbym:

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

Funkcja pairs () zamienia obiekt wejściowy w tablicę tablic klucz / wartość. Robisz to, aby łatwiej było używać odrzucania () do eliminowania undefinedi nullwartości. Następnie pozostają pary, które nie zostały odrzucone, a te są danymi wejściowymi dla zipObject () , który rekonstruuje dla Ciebie obiekt.

Adam Boduch
źródło
3

Biorąc pod uwagę, że undefined == nullmożemy napisać następująco:

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

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

Przykład JSBin

Andrejs
źródło
1
wracając do tego ... nie wiem dlaczego, ale tym razem musiałem użyć _.omitBy ... json = _.omitBy (json, (it) => it == null);
danday74
2

pickBy domyślnie używa tożsamości :

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
źródło
Podoba mi się ta krótsza wersja odpowiedzi @ Tx3. Działa ładnie!
Jordania
2

Najkrótsza droga (lodash v4):

_.pickBy(my_object)
Wasyl Boroviak
źródło
1

Z lodash (lub podkreśleniem) Możesz to zrobić

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

W przeciwnym razie za pomocą waniliowego JavaScript możesz to zrobić

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

Nie używać testu falsey, ponieważ nie tylko „undefined” lub „null” zostanie odrzucone , ale także inne wartości falsey, takie jak „false”, „0”, pusty ciąg, {}. Dlatego, aby uczynić to prostym i zrozumiałym, zdecydowałem się użyć wyraźnego porównania, jak zakodowano powyżej.

TaoPR
źródło
1
nie jest to jednak rekurencyjne
user3743222
1

Aby pominąć wszystkie wartości falsey , ale zachować wartości logiczne, to rozwiązanie pomaga.

_.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
źródło
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
źródło
1
_.reject traktuje dane wejściowe jako tablicę (uwzględnia tylko wartości, a nie klucze), a nie JSON. Wynikowy newObject to [2,4] nie {b: 2, c: 4}. Co więcej, nie odrzuca klucza „null”.
TaoPR
0

Użyłbym podkreślenia i zadbałbym też o puste ciągi:

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
źródło
0

Dla głęboko zagnieżdżonych obiektów i tablic. i wyklucz puste wartości z string i 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)

wynik:

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

Dla tych z was, którzy chcą usunąć z tablicy obiektów i użyć lodash, mogą zrobić coś takiego:


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

Uwaga: nie musisz niszczyć, jeśli nie chcesz.

User_coder
źródło