Удаление элементов в массиве с помощью 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";