Удаление элементов в массиве с помощью Lodash

У меня есть этот массив:

var fruits = ['Apple', 'Banana', 'Orange', 'Celery'];

И я использую Lodash remove следующим образом:

_.remove(fruits, function (fruit) {
  return fruit === 'Apple' || 'Banana' || 'Orange';
})

Результат ['Apple', 'Banana', 'Orange', 'Celery'], в то время как я ожидал, что оно будет ['Apple', 'Banana', 'Orange']. Почему это так?

Ответы

Ответ 1

Потому что, когда fruit является "Celery", вы тестируете:

"Celery" === 'Apple' || 'Banana' || 'Orange'

который оценивается как

false || true || true

который равен true.

Вы не можете использовать этот синтаксис. Либо сделайте это длинным путем:

_.remove(fruits, function (fruit) {
  return fruit === 'Apple' || fruit === 'Banana' || fruit === 'Orange'
});

или проверить принадлежность к массиву:

_.remove(fruits, function (fruit) {
  return _.indexOf(['Apple', 'Banana', 'Orange'], fruit) !== -1
});

Это не ограничивается JavaScript и на самом деле является распространенной ошибкой (например, этот вопрос)

Ответ 2

Вы можете использовать метод _.pull от lodash 2.0 и вверх

var fruits = ['Apple', 'Banana', 'Orange', 'Celery'];

_.pull(fruits, 'Apple', 'Banana', 'Orange'); // ['Celery']

document.write(fruits);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.6.1/lodash.js"></script>

Ответ 3

Проблема не в Lo-Dash; ваша проблема связана с вашим условным в вашей функции обратного вызова. Это:

return fruit === 'Apple' || 'Banana' || 'Orange';

Правильно ли не. Вам нужно сравнить fruit с каждой строкой:

return fruit === 'Apple' || fruit === 'Banana' || fruit === 'Orange';

Или вы можете использовать другую функцию Lo-Dash, чтобы сделать ее более компактной:

_.remove(fruits, function (fruit) {
  return _.contains(['Apple', 'Banana', 'Orange'], fruit);
})

Примечание: В последних версиях Lo-Dash функция _.contains устарела. Используйте _.includes

Ответ 4

Если вы хотите удалить набор элементов из другого набора, для этого предусмотрены определенные операции. Lodash имеет https://lodash.com/docs/4.17.2#difference, который принимает два параметра массива A и B и возвращает другой массив, который содержит все элементы A, которые не находятся в Б.

В вашем случае вы можете написать

const fruits = ['Apple', 'Banana', 'Orange', 'Celery'];
const filteredFruits = _.difference(fruits, ['Apple', 'Banana', 'Orange']);

что приведет к ['Celery'].

Ответ 5

Используйте массив значений, которые вы хотите сравнить, и проверьте, что возвращаемый индекс больше -1. Это указывает, что оцениваемое значение было найдено в коллекции.

_.remove( fruits, function ( fruit ) {
  return _.indexOf( [ "Apple", "Banana", "Orange" ], fruit ) >= 0;
});

В качестве альтернативы вы можете использовать lo-dash _.contains method, чтобы получить логический ответ.

Проблема с вашим подходом заключалась в том, что вы не сравнивали fruit с каждой из этих строк; вместо этого единственное сравнение имело место fruit против "Apple", после чего вы сами принудительно выполняли строки.

Непустые строки принуждают к true (!!"Banana") и, как таковые, являются правдивыми. Следовательно, следующее условие всегда будет короткозамкнуто в "Банане" (если fruit строго не равно "Apple"), возвращая true:

return fruit === "Apple" || 'Banana' || "Orange";