วิธีการลบค่าที่ไม่ได้กำหนดและค่าว่างจากวัตถุโดยใช้ lodash?


172

ฉันมีวัตถุ Javascript เช่น:

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

จะลบคุณสมบัติที่ไม่ได้กำหนดทั้งหมดได้อย่างไร คุณลักษณะที่ผิดควรอยู่

คำตอบ:


195

หากคุณต้องการลบค่าความผิดพลาดทั้งหมดวิธีที่กะทัดรัดที่สุดคือ:

สำหรับLodash 4.x และใหม่กว่า :

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

สำหรับLodash รุ่นเก่า 3.x:

_.pick(obj, _.identity);

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

63
โปรดทราบว่าใน Lodash 4 ควรเป็นเช่นนี้_.pickBy(obj, _.identity);
Tom Spencer

30
Plaese note วิธีนี้จะลบค่าเท็จ
ไม่ จำกัด

12
ระวังนี้จะลบบูลมีคุณสมบัติfalseValu
ไทรราม

6
นอกจากการลบ false มันจะลบแอททริบิวที่มีค่า 0 และ '' เป็นค่า ... ไม่ใช่ความคิดที่ดี
Federico Budassi

4
คำตอบนี้ไม่ได้เป็นค่าที่ถูกต้องเนื่องจากจะลบค่าที่ผิดพลาด ตรวจสอบคำตอบของฉันด้านล่าง
Tiago Bértolo

224

คุณสามารถเพียงแค่ห่วงโซ่_.omit()ด้วย_.isUndefinedและ_.isNullองค์ประกอบและได้รับผลการประเมินผลด้วยขี้เกียจ

การสาธิต

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

อัปเดต 14 มีนาคม 2559 :

ตามที่ระบุโดยดีแลนท์ในส่วนความคิดเห็นคุณควรใช้_.omitBy()ฟังก์ชั่นเนื่องจากมันใช้เพรดิเคตแทนคุณสมบัติ คุณควรใช้สิ่งนี้สำหรับรุ่น lodash 4.0.0และสูงกว่า

การสาธิต

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

อัปเดต 1 มิถุนายน 2559 :

ตามที่แสดงความคิดเห็นโดยMax Truxa lodash ได้เตรียมทางเลือกไว้_.isNilแล้วซึ่งจะตรวจสอบทั้งnullและundefined:

var result = _.omitBy(my_object, _.isNil);

7
ผู้ที่กำลังใช้รุ่นล่าสุดของ lodash ควรใช้ฟังก์ชั่นแทนomitBy omitดังนั้น_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
dylants

31
ตั้งแต่ lodash 4.0.0 คุณสามารถใช้_.isNilแทนการผูกมัดและ_.isUndefined _.isNullสิ่งนี้ทำให้สั้นยิ่งขึ้น:var result = _.omitBy(my_object, _.isNil);
Max Truxa

@ MaxTruxa คุณจะแก้ไขมันอย่างไรเพื่อตรวจสอบค่า "ไม่มี" ซ้ำ?
aegyed

1
ของ Lodash omitByนั้นมีประสิทธิภาพต่ำกว่าpickByดังนั้นจึงควรเลือกใช้งานหลังและเงื่อนไขในฟังก์ชัน iteratee จะกลับด้าน คำตอบที่ยอมรับข้างต้นมีสิทธิ์นั้น
Ernesto

1
คำถามของ OP ระบุไว้nullและundefinedค่าอย่างเดียว เพรดิเคตidentityจะลบfalseค่าดังนั้นหากคุณเพียงแค่ยึดตามเจตนาของคำถามฉันจะไม่เห็นปัญหากับคำตอบของฉัน นอกจากนี้หากเราพูดถึง "ประสิทธิภาพ" omitByเพียงแค่โทรpickByโดยใช้identityคำกริยาที่ไม่แสดงผลตามค่าเริ่มต้น ดังนั้นในแง่ของประสิทธิภาพมันเล็กเกินไปที่จะสำคัญ
ryeballar

38

หากคุณใช้ lodash คุณสามารถใช้_.compact(array)เพื่อลบค่าเท็จทั้งหมดออกจากอาร์เรย์

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

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


36
คอมแพคใช้กับอาร์เรย์ แต่คำถามเกี่ยวกับวัตถุ
guidoman

1
ยกเว้นฉันต้องการเก็บ 0 Argh ไว้ใกล้มาก
Sammi

2
@ Sami คุณสามารถใช้_.pickBy(object, _.isNumber)ในกรณีนั้นได้
John Rix

1
ขอบคุณ @Herick ที่ได้ผล ฉันจะไปนอนแล้ว
technophyle

1
@technophyle ฉันเห็นด้วยกับคุณ (และฉันเป็นคนที่เขียนคำตอบนี้ฮ่า) แต่ฉันก็รักษาคำตอบไว้ตรงนี้เพราะอย่างน้อยที่สุดมันก็แก้ปัญหาบางคนได้
JavaFish

25

คำตอบที่ถูกต้องคือ:

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

ผลลัพธ์เป็น:

{b: 1, d: false}

ทางเลือกให้คนอื่นที่นี่:

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

จะลบfalseค่าที่ไม่ต้องการด้วย


{"a":1,"b":{"a":1,"b":null,"c":undefined}}คุณสมบัติ object.b b'c' จะไม่ถูกลบ
mqliutie

@mqliutie ตามที่คาดไว้
Tiago Bértolo

18

แค่:

_.omit(my_object, _.isUndefined)

ด้านบนไม่ได้ใช้nullค่าบัญชีเนื่องจากมันหายไปจากตัวอย่างดั้งเดิมและกล่าวถึงเฉพาะในหัวเรื่อง แต่ฉันปล่อยให้มันเป็นแบบที่สวยงามและอาจมีการใช้งาน

นี่คือตัวอย่างที่สมบูรณ์ไม่รัดกุม แต่สมบูรณ์กว่า

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

8
โปรดทราบว่านี่สำหรับ Lodash v.3 สำหรับ v.4, _.omitByคุณต้องใช้
PhiLho

16

เพื่อให้คำตอบอื่น ๆ ให้สมบูรณ์ใน lodash 4 เพื่อละเว้นเฉพาะ undefined และ null (และไม่ใช่คุณสมบัติที่ต้องการfalse) คุณสามารถใช้เพรดิเคตใน_.pickBy:

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

ตัวอย่างด้านล่าง:

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>


1
นี้เป็นทางออกที่ดีที่สุดถ้าคุณไม่ต้องการที่จะลบ0, '', falseค่า นอกจากนี้คุณสามารถตัดการโทรกลับให้สั้นลงv => v != nullได้
SimpleJ

2
ทางออกที่ง่าย ขอบคุณสำหรับสิ่งนี้.
Arjun G Perambra

10

อ้างอิงจากเอกสาร lodash:

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

นอกจากนี้คุณสามารถกรองโมฆะทั้งหมด


6

สำหรับวัตถุที่ซ้อนกันลึกคุณสามารถใช้ตัวอย่างของฉันสำหรับ 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
};

5

ฉันพบปัญหาคล้ายกันกับการลบออกundefinedจากวัตถุ (ลึก) และพบว่าหากคุณตกลงที่จะแปลงวัตถุเก่าธรรมดาของคุณและใช้ JSON ฟังก์ชั่นตัวช่วยด่วนและสกปรกจะมีลักษณะเช่นนี้:

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

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

"... หากไม่ได้กำหนดฟังก์ชันหรือสัญลักษณ์ที่พบในระหว่างการแปลงจะถูกละเว้น (เมื่อพบในวัตถุ) หรือตัดเป็น null (เมื่อพบในอาเรย์)"


5

ด้วย JavaScript ที่แท้จริง: (แม้ว่า Object.entries คือ ES7, Object.assign คือ ES6 แต่ ES5 ที่เทียบเท่ากันใช้ Object.keys เท่านั้นที่ควรจะทำได้); แจ้งให้ทราบล่วงหน้าv != nullตรวจสอบทั้ง null และ undefined;

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

แก้ไข: ด้านล่างนี้เป็นรุ่นที่มี ES5 Object.keys เท่านั้น: แต่โดยทั่วไปกับ ES7 ใน Node v8 นั้นสนุกมาก ;-)

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

อัปเดตในเดือนตุลาคม 2560 : ด้วย Node v8 (ตั้งแต่ v8.3 หรือมากกว่านั้น) ตอนนี้มันมีโครงสร้างการแพร่กระจายวัตถุ:

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

หรือภายในหนึ่งลดเท่านั้น:

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

อัปเดต: บางคนต้องการเรียกซ้ำ ไม่ยากเช่นกันเพียงแค่ต้องตรวจสอบ isObject เพิ่มเติมและเรียกตัวเองซ้ำ ๆ ว่า:

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

ข้อสรุปของฉัน: หาก Javascript บริสุทธิ์สามารถทำได้ฉันจะหลีกเลี่ยงการพึ่งพาห้องสมุดบุคคลที่สาม:


คุณสามารถใช้Object.fromEntriesเพื่อหลีกเลี่ยงการใช้การลด: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! = null))
ppierre

5

เนื่องจากคุณบางคนอาจมาถึงคำถามที่ต้องการลบโดยเฉพาะเท่านั้น undefinedคุณสามารถใช้:

  • การรวมกันของวิธีการ Lodash

    _.omitBy(object, _.isUndefined)
  • rundefแพคเกจที่เอาเฉพาะundefinedคุณสมบัติ

    rundef(object)

หากคุณต้องการลบคุณสมบัติซ้ำแพคเกจยังมีตัวเลือกundefinedrundefrecursive

rundef(object, false, true);

ดูเอกสารประกอบสำหรับรายละเอียดเพิ่มเติม


3

นี่คือวิธี lodash ฉันจะใช้:

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

คู่ ()ฟังก์ชั่นเปลี่ยนวัตถุการป้อนข้อมูลลงในอาร์เรย์ของคีย์ / อาร์เรย์มูลค่า คุณทำเช่นนี้เพื่อให้ง่ายต่อการใช้ปฏิเสธ ()เพื่อกำจัดundefinedและnullค่า หลังจากนั้นคุณจะเหลือคู่ที่ไม่ได้ปฏิเสธและสิ่งเหล่านี้เป็นอินพุตสำหรับzipObject ()ซึ่งสร้างวัตถุของคุณใหม่


3

คำนึงถึงว่าundefined == nullเราสามารถเขียนได้ดังนี้:

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

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

ตัวอย่าง JSBin


1
revisiting สิ่งนี้ ... ไม่แน่ใจว่าทำไม แต่คราวนี้ฉันต้องใช้ _.omitBy ... json = _.omitBy (json, (it) => มัน == null);
danday74



1

ด้วย lodash (หรือขีดล่าง) คุณสามารถทำได้

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

มิฉะนั้นด้วยวานิลลา JavaScript คุณสามารถทำได้

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

ที่จะไม่ใช้การทดสอบเท็จเพราะไม่เพียง แต่ "undefined" หรือ "null" จะถูกปฏิเสธนอกจากนี้ยังมีค่าเท็จอื่น ๆ เช่น "false", "0", สตริงว่าง {} ดังนั้นเพื่อให้ง่ายและเข้าใจได้ฉันเลือกที่จะใช้การเปรียบเทียบที่ชัดเจนตามรหัสด้านบน


1
นี่ไม่ใช่การเรียกซ้ำ
user3743222

1

หากต้องการละเว้นค่าเท็จทั้งหมดแต่เก็บบูลีนแบบดั้งเดิมโซลูชันนี้จะช่วย

_.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/lodash@4.17.11/lodash.min.js"></script>


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 }

1
_.reject ถือว่าอินพุตเป็นอาร์เรย์ (ใช้ได้เฉพาะกับค่าไม่ใช่คีย์) ไม่ใช่ JSON newObject ที่เป็นผลลัพธ์คือ [2,4] ไม่ใช่ {b: 2, c: 4} เพิ่มเติมมันไม่ได้ปฏิเสธปุ่ม "null"
TaoPR

0

ฉันจะใช้ขีดล่างและดูแลสตริงว่างด้วยเช่นกัน:

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


0

สำหรับวัตถุและอาร์เรย์ที่ซ้อนกันลึก และแยกค่าว่างจากสตริงและ 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)

ผลลัพธ์:

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

0

ฉันชอบใช้ _.pickBy เพราะคุณสามารถควบคุมสิ่งที่คุณลบได้อย่างสมบูรณ์:

var person = {"name":"bill","age":21,"sex":undefined,"height":null};

var cleanPerson = _.pickBy(person, function(value, key) {
  return !(value === undefined || value === null);
});

ที่มา: https://www.codegrepper.com/?search_term=lodash+remove+undefined+values+from+object


0

สำหรับคนที่คุณต้องการมาที่นี่เพื่อลบออกจากอาเรย์ของวัตถุและใช้ lodash คุณสามารถทำสิ่งนี้:


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

หมายเหตุ:คุณไม่จำเป็นต้องทำลายล้างหากคุณไม่ต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.