Как удалить неопределенные и нулевые значения из объекта, используя lodash?

173

У меня есть объект Javascript, как:

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

Как удалить все неопределенные свойства? Ложные атрибуты должны остаться.

JLavoie
источник

Ответы:

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}
Tx3
источник
63
Обратите внимание, что в 4-м лодах это должно быть_.pickBy(obj, _.identity);
Том Спенсер
30
Обратите внимание, этот метод также удалит ложное значение.
ограничений
12
Будьте осторожны, это удалит логическое свойство , имеющее falseВалу
Sai Ram
6
Помимо удаления false, он также удалит атрибуты с 0 и '' в качестве значения ... не очень хорошая идея.
Федерико Будасси
4
Этот ответ не является корректным, поскольку он также удаляет ложные значения. Проверьте мой ответ ниже.
Тьяго Бертоло
225

Вы можете просто цепь _.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 года :

Как прокомментировал Макс Truxa , lodash уже предоставили альтернативу _.isNil, который проверяет , как nullи undefined:

var result = _.omitBy(my_object, _.isNil);
ryeballar
источник
7
Те, кто использует более свежие версии lodash, должны использовать omitByфункцию вместо omit. Итак_(my_object).omitBy(_.isUndefined).omitBy(_.isNull).value();
2016 года
31
Начиная с lodash 4.0.0 вы можете использовать _.isNilвместо цепочки _.isUndefinedи _.isNull. Это делает его еще короче:var result = _.omitBy(my_object, _.isNil);
Макс Трукса
@MaxTruxa, как бы вы изменили его, чтобы рекурсивно проверять значения "Nil"?
Aegyed
1
Lodash omitByменее производительный чем pickBy, поэтому последний должен быть предпочтительным, и условие в функции iteratee полностью изменено. Принятый ответ выше получил это право.
Эрнесто
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

JavaFish
источник
36
Compact относится к массивам, но вопрос об объектах
guidoman
1
За исключением того, что я хочу оставить 0. Argh, так близко.
Самми
2
@ Самми, вы можете использовать _.pickBy(object, _.isNumber)в этом случае.
Джон Рикс
1
Спасибо @Herick. Это работает. Я сейчас пойду спать.
технофил
1
@ technophyle, я согласен с тобой (и я тот, кто написал этот ответ, ха). Но я держу этот ответ здесь, потому что он, по крайней мере, решает проблемы некоторых людей.
JavaFish
26

Правильный ответ:

_.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); }));
PhiLho
источник
8
Обратите внимание, что это для Lodash v.3. Для v.4 вы должны использовать _.omitBy.
Филип
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>

nSimonFR
источник
1
Это лучшее решение , если вы не хотите , чтобы удалить 0, '', falseзначение. Также вы можете сократить обратный вызов до v => v != null.
SimpleJ
2
Простое решение Спасибо тебе за это.
Арджун Дж Перамбра
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
};
1nstinct
источник
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, я бы избегал любых сторонних библиотечных зависимостей:

user5672998
источник
Вы можете использовать Object.fromEntries, чтобы избежать использования redu: Object.fromEntries (Object.entries (d) .filter (([k, v]) => (v! = Null)))
Null
5

Поскольку некоторые из вас, возможно, пришли к вопросу о том, чтобы конкретно удалить только undefined , вы можете использовать:

  • комбинация методов Лодаша

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

    rundef(object)

Если вам нужно рекурсивно удалить undefinedсвойства, в rundefпакете также есть recursiveопция.

rundef(object, false, true);

Смотрите документацию для более подробной информации.

d4nyll
источник
3

Вот какой подход я бы выбрал:

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

Функция pair () превращает входной объект в массив массивов ключ / значение. Вы делаете это так, чтобы было проще использовать 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);
danday74
2

pickBy использует идентичность по умолчанию:

_.pickBy({ a: null, b: 1, c: undefined, d: false });
chrisandrews7
источник
Мне нравится эта более короткая версия ответа @ Tx3. Работает красиво!
Иордания
2

Кратчайший путь (lodash v4):

_.pickBy(my_object)
Василий Боровяк
источник
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];
    }
});

Не использовать тест Falsey, потому что будет отклонено не только «undefined» или «null» , но и другое значение «falsey», например «false», «0», пустая строка, {}. Таким образом, просто чтобы сделать его простым и понятным, я решил использовать явное сравнение, как написано выше.

TaoPR
источник
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 }
JLavoie
источник
1
_.reject обрабатывает ввод как массив (он учитывает только значения, а не ключи), а не JSON. Результирующий newObject [2,4] не {b: 2, c: 4}. Кроме того, он не отклоняет «нулевой» ключ.
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 .

mrgoos
источник
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"
}
Gleidosn
источник
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' }]

Примечание: вам не нужно разрушать, если вы не хотите.

User_coder
источник