Як видалити невизначені та нульові значення з об’єкта за допомогою 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
Зауважте, що в квартирі 4 це має бути_.pickBy(obj, _.identity);
Том Спенсер

30
Зауважте, що цей метод також видалить помилкове значення.
необмежено

12
Будьте уважні, це вилучить булеву власність, яка має falseцінність
Сай Рам,

6
Крім видалення помилок, він також видалить атрибути із значенням 0 та '' ... не дуже гарна ідея.
Федеріко Будассі

4
Ця відповідь не є коректною, оскільки вона також видаляє помилкові значення. Перевірте мою відповідь нижче.
Тіаго Бертоло

224

Ви можете просто ланцюг _.omit()з _.isUndefinedі _.isNullкомпозицією, і отримати результат з ледачою оцінкою.

Демо

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

Оновлення 14 березня 2016 року :

Як зазначають dylants в розділі коментарів, ви повинні використовувати _.omitBy()функцію, оскільки вона використовує предикат замість властивості. Ви повинні використовувати це для версії lodash 4.0.0та вище.

DEMO

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

Оновлення 1 червня 2016 року :

Як коментує Макс Трукса , lodash вже запропонував альтернативу _.isNil, яка перевіряє і те, nullі інше undefined:

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

7
Ті, хто використовує новіші версії lodash, повинні використовувати omitByфункцію замість omit. Отже_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
диланти

31
З lodash 4.0.0 ви можете використовувати _.isNilзамість ланцюжка _.isUndefinedта _.isNull. Це робить його ще коротшим:var result = _.omitBy(my_object, _.isNil);
Макс Трукса

@MaxTruxa як би змінити його, щоб перевірити значення "Nil" рекурсивно?
аегід

1
Лодаш omitByменш ефективний, ніж pickByостанній, тому слід віддавати перевагу останньому, а стан функції ітерації - зворотним. Прийнята вище відповідь отримала це право.
Ернесто

1
Питання ОП лише вказане 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
Компактний стосується масивів, але питання стосується об'єктів
гідоман

1
За винятком того, що я хочу тримати 0. Argh, так близько.
Саммі

2
@Sammi, ви можете використовувати _.pickBy(object, _.isNumber)в цьому випадку.
Джон Рікс

1
Дякую @Herick Це працює. Я зараз піду спати.
технофіл

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, як очікувалося.
Тіаго Бертоло

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. Для версії 4 ви повинні використовувати _.omitBy.
PhiLho

16

Щоб завершити інші відповіді, у lodash 4, щоб ігнорувати лише невизначені та 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

"... Якщо під час перетворення виникає невизначена функція або символ, вона або пропущена (коли вона знайдена в об'єкті), або цензурована на нуль (коли вона знайдена в масиві)."


5

з чистим JavaScript: (хоча Object.entries - ES7, Object.assign - ES6; але еквівалентний ES5 використовує лише Object.keys, також слід зробити); також помітити v != nullперевірки як на нульові, так і на невизначені;

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

Оновлення в жовтні 2017 року : з 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 , ви можете використовувати:

  • поєднання методів Лодаша

    _.omitBy(object, _.isUndefined)
  • rundefпакет, який видаляє тільки undefinedвластивості

    rundef(object)

Якщо вам потрібно рекурсивно видалити undefinedвластивості, rundefпакет також має recursiveможливість.

rundef(object, false, true);

Детальнішу інформацію див. У документації .


3

Ось такий підхід, який я застосую:

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

Функція пар () перетворює об'єкт введення в масив масивів ключ / значення. Ви робите це, щоб легше було використовувати функцію reject () для усунення 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
переглянувши це ... не впевнений, чому, але цього разу мені довелося використовувати _.omitBy ... json = _.omitBy (json, (it) => it == null);
понеділок74



1

З подачею (або підкресленням) ви можете це зробити

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

Не використовувати тест фальси, тому що не тільки "невизначене" або " нулеве " буде відхилено , а й інше значення фальси, як "хибне", "0", порожня рядок, {}. Таким чином, щоб зробити його простим і зрозумілим, я вирішив використовувати явне порівняння, як зашифроване вище.


1
це не є рекурсивним
користувач3743222

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. Отриманий новийОб'єкт [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

Для тих, хто потрапляє сюди, шукаючи видалити з масиву об’єктів і за допомогою 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' }]

Примітка: Вам не потрібно руйнувати, якщо цього не хочете.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.