Bagaimana cara menghapus nilai yang tidak terdefinisi dan null dari suatu objek menggunakan lodash?

172

Saya memiliki objek Javascript seperti:

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

Bagaimana cara menghapus semua properti yang tidak terdefinisi? Atribut palsu harus tetap ada.

JLavoie
sumber

Jawaban:

195

Jika Anda ingin menghapus semua nilai falsey maka cara yang paling ringkas adalah:

Untuk Lodash 4.x dan yang lebih baru :

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

Untuk warisan Lodash 3.x:

_.pick(obj, _.identity);

_.pick({ a: null, b: 1, c: undefined }, _.identity);
>> Object {b: 1}
Tx3
sumber
63
Harap dicatat bahwa dalam lodash 4 ini seharusnya_.pickBy(obj, _.identity);
Tom Spencer
30
Jika diperhatikan, metode ini juga akan menghapus nilai palsu.
terbatas
12
Hati-hati, ini akan menghapus properti boolean memiliki falsevalu
Sai Ram
6
Selain menghapus false, itu juga akan menghapus atribut dengan nilai 0 dan '' sebagai nilai ... bukan ide yang baik.
Federico Budassi
4
Jawaban ini tidak benar karena itu juga menghilangkan nilai-nilai palsu. Periksa jawaban saya di bawah ini.
Tiago Bértolo
225

Anda hanya dapat rantai _.omit()dengan _.isUndefineddan _.isNullkomposisi, dan mendapatkan hasil dengan evaluasi malas.

Demo

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

Pembaruan 14 Maret 2016 :

Seperti yang disebutkan oleh dylants di bagian komentar, Anda harus menggunakan _.omitBy()fungsi ini karena menggunakan predikat alih-alih properti. Anda harus menggunakan ini untuk versi lodash ke 4.0.0atas.

DEMO

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

Pembaruan 1 Juni 2016 :

Seperti dikomentari oleh Max Truxa , lodash sudah memberikan alternatif _.isNil, yang memeriksa keduanya nulldan undefined:

var result = _.omitBy(my_object, _.isNil);
ryeballar
sumber
7
Mereka yang menggunakan versi terbaru dari Lodash harus menggunakan omitByfungsi alih-alih omit. Jadi_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants
31
Sejak lodash 4.0.0 Anda dapat menggunakan _.isNilalih-alih chaining _.isUndefineddan _.isNull. Ini membuatnya lebih pendek:var result = _.omitBy(my_object, _.isNil);
Max Truxa
@ MaxTruxa bagaimana Anda memodifikasinya untuk memeriksa nilai "Nil" secara rekursif?
aegyed
1
Lodash omitBykurang performan daripada pickBy, jadi yang terakhir harus lebih disukai, dan kondisi dalam fungsi iteratee terbalik. Jawaban yang diterima di atas benar.
Ernesto
1
Pertanyaan OP hanya ditentukan nulldan undefinednilainya. The identitypredikat juga akan menghapus falsenilai-nilai, jadi jika Anda hanya berdasarkan itu atas pertanyaan ini niat maka saya tidak melihat masalah dengan jawaban saya. Selain itu, jika kita membahas "kinerja", omitBycukup panggil pickBydengan identitypredikat yang dinegasikan , secara default. Jadi, dalam hal kinerja, terlalu kecil untuk menjadi signifikan.
ryeballar
38

jika Anda menggunakan lodash, Anda bisa menggunakan _.compact(array)untuk menghapus semua nilai palsu dari array.

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

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

JavaFish
sumber
36
compact berlaku untuk array tetapi pertanyaannya adalah tentang objek
guidoman
1
Kecuali saya ingin menyimpan 0. Argh, sangat dekat.
Sammi
2
@ Sammi, Anda dapat menggunakan _.pickBy(object, _.isNumber)dalam kasus itu.
John Rix
1
@Herick terima kasih. Itu bekerja. Saya akan tidur sekarang.
technophyle
1
@ technophyle, saya setuju dengan Anda (dan saya yang menulis jawaban ini, ha). Tetapi saya menyimpan jawaban ini di sini karena, paling tidak, memecahkan beberapa masalah masyarakat.
JavaFish
25

Jawaban yang benar adalah:

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

Itu menghasilkan:

{b: 1, d: false}

Alternatif yang diberikan di sini oleh orang lain:

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

Akan menghapus juga falsenilai-nilai yang tidak diinginkan di sini.

Tiago Bértolo
sumber
{"a":1,"b":{"a":1,"b":null,"c":undefined}}, properti object.b b, 'c' tidak akan dihapus
mqliutie
@ mqliutie seperti yang diharapkan.
Tiago Bértolo
18

Hanya:

_.omit(my_object, _.isUndefined)

Hal di atas tidak memperhitungkan nullnilai akun , karena tidak ada dalam contoh asli dan hanya disebutkan dalam subjek, tetapi saya membiarkannya karena elegan dan mungkin memiliki kegunaannya.

Berikut adalah contoh lengkapnya, kurang ringkas, tetapi lebih lengkap.

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
sumber
8
Perhatikan bahwa ini untuk Lodash v.3. Untuk v.4, Anda harus menggunakan _.omitBy.
PhiLho
16

Untuk melengkapi jawaban lain, dalam lodash 4 untuk mengabaikan hanya undefined dan null (Dan bukan sifat suka false) Anda dapat menggunakan predikat di _.pickBy:

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

Contoh di bawah ini:

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
sumber
1
Ini adalah solusi terbaik jika Anda tidak ingin menghapus 0, '', falsenilai-nilai. Anda juga dapat mempersingkat panggilan balik ke v => v != null.
SimpleJ
2
Solusi sederhana. Terima kasih untuk ini.
Arjun G Perambra
10

Menurut dokumen Lodash:

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

Anda juga dapat memfilter semua nol

Oleg Koval
sumber
6

Untuk objek bersarang mendalam, Anda dapat menggunakan potongan saya untuk 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 naluri
sumber
5

Saya mengalami masalah yang sama dengan menghapus undefineddari suatu objek (dalam), dan menemukan bahwa jika Anda OK untuk mengkonversi objek lama polos Anda dan menggunakan JSON, fungsi pembantu yang cepat dan kotor akan terlihat seperti ini:

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

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

"... Jika tidak terdefinisi, suatu fungsi, atau simbol ditemukan selama konversi, maka itu dihilangkan (ketika ditemukan dalam suatu objek) atau disensor ke nol (ketika ditemukan dalam array)."

Jerome
sumber
5

dengan JavaScript murni: (meskipun Object.entries adalah ES7, Object.assign adalah ES6; tetapi ES5 yang setara menggunakan Object.keys hanya juga bisa dilakukan); juga perhatikan v != nullcek untuk null dan tidak terdefinisi;

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

Sunting: ini di bawah ini adalah versi dengan ES5 Object.keys saja: tetapi secara umum dengan ES7 di Node v8 cukup menyenangkan ;-)

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

Pembaruan pada Oktober 2017 : dengan Node v8 (sejak v8.3 atau lebih) sekarang ia memiliki konstruksi penyebaran objek:

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

atau dalam satu pengurangan saja:

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

Perbarui: seseorang ingin rekursif? tidak sulit juga, hanya perlu memeriksa isObject tambahan, dan menyebut dirinya sendiri secara rekursif:

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

kesimpulan saya: jika Javascript murni dapat melakukannya, saya akan menghindari ketergantungan perpustakaan pihak ketiga:

pengguna5672998
sumber
Anda dapat menggunakan Object.fromEntries untuk menghindari pengurangan: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! = Null)))
ppierre
5

Karena beberapa dari Anda mungkin telah tiba di pertanyaan mencari untuk secara khusus menghapus hanya undefined , Anda dapat menggunakan:

  • kombinasi metode Lodash

    _.omitBy(object, _.isUndefined)
  • yang rundefpaket, yang menghilangkan hanya undefinedsifat

    rundef(object)

Jika Anda perlu menghapus properti secara rekursifundefined , rundefpaket juga memiliki recursiveopsi.

rundef(object, false, true);

Lihat dokumentasi untuk lebih jelasnya.

d4nyll
sumber
3

Inilah pendekatan lodash yang akan saya ambil:

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

Fungsi pasangan () mengubah objek input menjadi array array kunci / nilai. Anda melakukan ini sehingga lebih mudah menggunakan tolak () untuk menghilangkan undefineddan nullmenghargai. Setelah itu, Anda pergi dengan pasangan yang tidak ditolak, dan ini adalah input untuk zipObject () , yang merekonstruksi objek Anda untuk Anda.

Adam Boduch
sumber
3

Dengan memperhitungkan itu undefined == nullkita bisa menulis sebagai berikut:

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

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

Contoh JSBin

Andrejs
sumber
1
meninjau kembali ini ... tidak yakin mengapa tetapi kali ini saya harus menggunakan _.omitBy ... json = _.omitBy (json, (it) => it == null);
danday74
2

pickBy menggunakan identitas secara default:

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
sumber
Saya suka versi yang lebih pendek dari jawaban @ Tx3 ini. Bekerja dengan baik!
Jordan
2

Cara terpendek (lodash v4):

_.pickBy(my_object)
Vasyl Boroviak
sumber
1

Dengan lodash (atau garis bawah), Anda dapat melakukannya

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

Kalau tidak, dengan JavaScript vanilla, Anda bisa melakukannya

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

Tidak menggunakan tes falsey, karena tidak hanya "tidak terdefinisi" atau "null" akan ditolak , juga nilai falsey lainnya seperti "false", "0", string kosong, {}. Jadi, hanya untuk membuatnya sederhana dan dapat dimengerti, saya memilih untuk menggunakan perbandingan eksplisit seperti yang dikodekan di atas.

TaoPR
sumber
1
ini bukan rekursif
user3743222
1

Untuk menghilangkan semua nilai falsey tetapi menjaga primitif boolean solusi ini membantu.

_.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
sumber
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
sumber
1
_.reject memperlakukan input sebagai array (hanya memperhitungkan nilai, bukan kunci), bukan JSON. NewObject yang dihasilkan adalah [2,4] bukan {b: 2, c: 4}. Lebih lanjut, itu tidak menolak kunci "null".
TaoPR
0

Saya akan menggunakan garis bawah dan merawat string kosong juga:

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

Untuk objek dan array bersarang yang dalam. dan mengecualikan nilai kosong dari string dan 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)

hasil:

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

Bagi Anda yang ingin mencari di sini untuk menghapus dari array objek dan menggunakan lodash Anda dapat melakukan sesuatu seperti ini:


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

Catatan: Anda tidak harus merusak jika tidak mau.

User_coder
sumber