Как пропустить элемент в .map()?
Как пропустить элемент массива в методе .map
?
Я пытаюсь использовать метод .map
для преобразования массива изображений, но мне нужно пропустить элементы с определенным условием. В частности, я хочу игнорировать элементы, у которых расширение json
.
Вот мой код:
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // если расширение .json
return null; // пропустить
}
else{
return img.src;
}
});
Однако, когда я выполняю этот код, он возвращает массив с null
для пропущенных элементов:
["img.png", null, "img.png"]
Как я могу изменить свой код, чтобы просто исключать элементы с json
из результатов, а не возвращать null
?
5 ответ(ов)
Вы можете использовать метод .filter()
для фильтрации элементов в массиве, а затем применить .map()
для извлечения нужных значений. Вот пример:
var sources = images.filter(function(img) {
if (img.src.split('.').pop() === "json") {
return false; // пропустим
}
return true;
}).map(function(img) { return img.src; });
Если вы хотите избежать использования .filter()
, что не является неразумным, так как это имеет некоторые накладные расходы, вы можете воспользоваться более универсальным методом .reduce()
. В общем, .map()
можно выразить через .reduce()
следующим образом:
someArray.map(function(element) {
return transform(element);
});
можно записать как:
someArray.reduce(function(result, element) {
result.push(transform(element));
return result;
}, []);
Таким образом, если вам нужно пропустить некоторые элементы, это можно сделать с помощью .reduce()
:
var sources = images.reduce(function(result, img) {
if (img.src.split('.').pop() !== "json") {
result.push(img.src);
}
return result;
}, []);
В этой версии код из .filter()
, приведённый в первом примере, стал частью колбэка .reduce()
. Исходный путь изображения добавляется в результирующий массив только в том случае, если операция фильтрации позволила бы его сохранить.
Обновление — Этот вопрос вызывает много интереса, и я хотел бы добавить следующее пояснение. Цель метода .map()
, как концепта, заключается в преобразовании списка значений в другой список значений в соответствии с определёнными правилами. Так же как бумажная карта какой-либо страны будет выглядеть странно, если на ней не будет нескольких городов, отображение из одного списка в другой имеет смысл, только если существует взаимно однозначное соответствие значений.
Я не утверждаю, что создание нового списка из старого с исключением некоторых значений не имеет смысла. Я просто хочу прояснить, что .map()
имеет одно простое намерение — создать новый массив такой же длины, как старый массив, только с элементами, образованными путём преобразования старых значений.
Использование forEach
для фильтрации массива, как в вашем примере, возможно, но это не самый оптимальный и читаемый способ решения данной задачи. Давайте разберёмся, почему лучше использовать метод filter
.
Когда вы используете forEach
, вам нужно создавать дополнительный массив (filtered
) и вручную добавлять в него элементы, которые удовлетворяют вашему условию. Это может привести к увеличению объема кода и снижению его читаемости. Кроме того, в случае больших массивов это может повлиять на производительность, так как вам нужно выполнять два действия: проходить по массиву и добавлять элементы в новый массив.
С другой стороны, метод filter
уже встроен в массивы и делает именно то, что вам нужно, за один шаг. Он проходит через каждый элемент массива, применяет указанную функцию и возвращает новый массив с элементами, которые удовлетворяют условию. Это более лаконично, и код выглядит чище:
const arr = ['a', 'b', 'c', 'd', 'e'];
const filtered = arr.filter(x => !x.includes('b')); // ['a','c','d','e'];
Таким образом, использование filter
предпочтительнее с точки зрения читаемости, производительности и выражения намерений. Вы сразу понимаете, что собираетесь отфильтровать элементы, и код становится более декларативным. В общем, рекомендуется использовать filter
, когда вам нужно отфильтровать массивы по условию.
Чтобы убрать все null
значения из массива things
, можно использовать метод reduce
, как в приведённом вами примере. Ваш код корректен, вот краткий разбор:
const thingsWithoutNulls = things.reduce((acc, thing) => {
if (thing !== null) {
acc.push(thing);
}
return acc;
}, []);
Здесь мы инициализируем аккумулятор acc
как пустой массив. Затем для каждого элемента thing
в исходном массиве things
проверяем, не равен ли он null
. Если это так, добавляем его в аккумулятор. В итоге возвратим массив, который не содержит null
значений.
Однако, для этой задачи также можно использовать метод filter
, он более лаконичен:
const thingsWithoutNulls = things.filter(thing => thing !== null);
Этот способ более читаем и выполняет ту же задачу, возвращая новый массив без null
значений.
Вот перевод вашего кода на русский, выполненный в стиле ответа на StackOverflow:
var sources = images.map(function (img) {
if(img.src.split('.').pop() === "json"){ // если расширение .json
return null; // пропускаем
}
else{
return img.src; // возвращаем источник изображения
}
}).filter(Boolean); // .filter(Boolean) удаляет все ложные значения из массива, в данном случае null.
В данном коде происходит следующее: мы перебираем массив images
с помощью метода map
. Проверяем, имеет ли каждый элемент расширение .json
. Если да, то возвращаем null
, чтобы пропустить этот элемент. В противном случае возвращаем источник изображения. Затем с помощью метода filter(Boolean)
мы отфильтровываем все ложные значения, что позволяет удалить все null
из результирующего массива sources
.
В приведённом вами примере кода создаётся массив arr
, который содержит различные значения, включая нули, пустую строку, undefined
, false
, null
и NaN
. Затем используется метод filter
с передачей функции-конструктора Boolean
. Этот метод фильтрует массив, оставляя только "истинные" значения.
Вот как это работает:
Boolean
— это встроенная функция, которая преобразует переданное ей значение в булевый тип. В JavaScript значения, которые считаются ложными (falsy), это:0
,""
(пустая строка),undefined
,null
,false
иNaN
.- Когда мы передаём
Boolean
вfilter
, массив проходит по каждому элементу и оставляет только те, которые имеют истинное (truthy) значение.
В результате вызова arr.filter(Boolean)
мы получаем новый массив, который содержит только истинные значения из исходного массива:
const arr = [0, 1, '', undefined, false, 2, undefined, null, , 3, NaN];
const filtered = arr.filter(Boolean); // [ 1, 2, 3 ]
console.log(filtered);
Вывод на консоль будет: [1, 2, 3]
. Таким образом, элементы 0
, ''
, undefined
, false
, null
и NaN
были исключены из конечного массива.
Как перенаправить на другую веб-страницу?
Где найти документацию по форматированию даты в JavaScript?
Как выполнить функцию JavaScript, имея её имя в виде строки
В чем разница между String.slice и String.substring?
Проверка соответствия строки регулярному выражению в JS