#javascript #arrays
Вопрос:
Я пытаюсь понять этот filter
метод. Я нашел пример скрипта и изменил его, чтобы умножить все элементы исходного массива на два:
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = (ar) => ar.filter((word, index, arr) => {
arr[index 1] *= 2
return true
})
console.log(multiplyByTwo(list))
}
Все, кроме первого элемента массива, будут изменены. Если я изменю значение arr[index 1]
на arr[index]
, ни один из элементов не будет изменен. Я пытаюсь понять, как это работает.
Ответ №1:
Как вы уже знаете map
, это правильный способ достижения упомянутого требования, позвольте мне попытаться объяснить, почему filter
это не работает.
Вы должны понимать возвращаемое значение фильтра, которое представляет собой новый массив с элементами, прошедшими тест.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
console.log("before = ", list);
const multiplyByTwo = (ar) =>
ar.filter((word, index, arr) => {
arr[index] *= 2; // <--- Manipulating the current list
return true; // <----- Return the current element: word
});
console.log("after = ", multiplyByTwo(list));
}
zeroFill();
В случае arr[index] * 2
, вы умножаете каждый элемент на 2 (и list
тоже изменяете массив), но возвращаете текущий элемент, представленный word
в приведенном выше коде.
Ответ №2:
filter
возвращает новый массив с элементами массива list
на основе его возвращаемого значения. Значения массива изменяются в обоих случаях, т. е. при использовании arr[index 1] *= 2
и arr[index] *= 2
. Однако значение, которое попадает в результирующий массив, совпадает с переданным значением word
.
Смотрите спецификацию:
- Элемент массива с индексом k массива O извлекается и сохраняется как значение.
- Функция обратного вызова вызывается с аргументами (значение, k, O).
- Если функция обратного вызова возвращает истинное значение, поместите значение kValue в результирующий массив.
Ни в коем случае элемент массива с индексом k массива O не извлекается снова.
Ваша модификация с arr[index] *= 2
всегда приходит слишком поздно; значение, которое будет добавлено, уже было извлечено из массива filter
методом. Ваши изменения с arr[index 1] *= 2
помощью изменят следующий индекс, который является значением, filter
получаемым на следующей итерации. Вот почему вы видите измененные значения, начиная с индекса 1
. Индекс 0
еще не видел изменений, поэтому filter
получает исходное значение и добавляет его в результирующий массив.
Регистрируйтесь list
не только multiplyByTwo(list)
для того , чтобы видеть измененные значения.
Вы злоупотребляете filter
здесь. Вместо этого вы должны использовать map
для изменения каждого значения на другое значение или forEach
, если вы хотите изменить массив с помощью чего-то подобного arr[index 1] *= 2
.
Чтобы умножить каждый элемент на два:
console.log(list.map((value) => value * 2));
Комментарии:
1. это очень помогает. В основном я пытался понять поведение метода фильтрации.
Ответ №3:
filter
Функция не предназначена для этой цели. Он предназначен для фильтрации необходимых вам элементов массива.
Для вашего конкретного случая я бы использовал .map
метод, так как он будет изменять массив по мере необходимости и предназначен для обхода массивов.
const multiplyByTwo = (ar) => ar.map((current) => current * 2);
Ответ №4:
Вы пытаетесь изменить массив, .filter
что не является хорошей практикой. Вы можете использовать .map
, когда хотите что-то сделать с элементами массива.
function zeroFill() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
console.log(list)
const multiplyByTwo = ( ar) => ar.map( (item, index, ) => {
return item *= 2
})
console.log(multiplyByTwo(list))
}
zeroFill();
Ответ №5:
Сначала я попытаюсь объяснить, почему у вас такое поведение, запустите этот код и попытайтесь понять:
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
function zeroFill() {
console.log('list before filter: ', list)
const multiplyByTwo = ( ar) => ar.filter((word, index, arr) => {
console.log(arr === list); //arr and list have the same reference
arr[index] *= 2; //you will be modifing list[index], that is the current value being filtered, so you you will get the old value
//arr[index 1] *= 2; //you will modifying list[index 1], so in the next loop the value will be the new one
return true
}); //The result of filter will create a new array
console.log('multiplyByTwo result:', multiplyByTwo(list))
console.log('list after filter: ', list);
}
Вы должны использовать .фильтр только для того, чтобы выбрать нужные значения на основе условия, а не для изменения массива во время его фильтрации, вы должны использовать .map для этой цели:
const list = [1, 0, 1, 2, 3, 0, 0, 4, 0];
const multiplyByTwo = list.map((current) => current * 2);
Ответ №6:
Array.filter()
, как указано в названии, фильтрует массив и возвращает новый массив, содержащий элементы, прошедшие фильтр.
Что вам нужно, так это Array.map()
если вам нужен сопоставленный (а также новый) массив. В противном случае вы можете использовать Array.forEach()
// In this function, a new array is created and returned, with modified items
function zeroFillWithMap() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
const multiplyByTwo = list.map(i => i*2)
console.log('Mapped New Array', multiplyByTwo)
}
zeroFillWithMap();
// In this function, a new array is NOT created and the items of the original array are modified
function zeroFillWithForEach() {
let list = [1, 0, 1, 2, 3, 0, 0, 4, 0]
list.forEach((item, index, originalArray) => originalArray[index] *= 2)
console.log('Modified Original Array', list)
}
zeroFillWithForEach();
Ответ №7:
Я не уверен, знаете ли вы о «Методе отображения в JS». Я думаю, что проблема, которую вы предложили, может быть решена гораздо проще с помощью этого метода. Я оставлю здесь свой код о том, как я решил вашу проблему.
const zeroFill = (list) => {
console.log("orignal array: " list);
const multiplyByTwo = list.map((item) => {
return item * 2;
});
console.log("multiplied by two array: " multiplyByTwo);
};
zeroFill([1, 0, 1, 2, 3, 0, 0, 4, 0]);
но если вам нужно, чтобы ваша проблема была решена только методом фильтрации, я был бы рад помочь и в этой ситуации.
И да, если вы хотите узнать больше о «Методе отображения в Javascript». Я собираюсь связать несколько статей из MDN и W3SCHOOL.
https://www.w3schools.com/jsref/jsref_map.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map