Мой последний пост касался рекурсивного Array.map
. Хотя это хороший учебный ресурс, я не рекомендую никому использовать его в своих приложениях.
То же самое касается рекурсивной реализации Array.filter
.
Вместо этой (упрощенной) традиционной версии:
filter = (predicate, arr) => { const filteredArray = []; for (let i = 0; i < arr.length; i++) { let currentItem = arr[i]; if (predicate(currentItem)) { filteredArray.push(currentItem); } } return filteredArray; };
Учти это:
filter = (pred, [head, ...tail]) => head === undefined ? [] : ( pred(head) ? [head, ...filter(pred, tail)] : [...filter(pred, tail)] );
Если вы понимаете рекурсивный массив.map
, это просто.
Мы по-прежнему фиксируем первый элемент массива в переменной с именем head
, а остальные - в отдельный массив с именем tail
.
И в том же базовом случае - если head
равно undefined
, вернуть пустой массив и завершить итерацию.
Но у нас есть еще один условный оператор: помещайте head
в новый массив, только если pred(head)
равно true
, потому что filter
работает, проверяя каждый элемент на соответствие функции предиката. Только когда предикат возвращает true
, мы добавляем этот элемент в новый массив.
Если pred(head)
не возвращает true
, просто позвоните filter(pred, tail)
без head
.
Давайте быстро рассмотрим это в консоли Chrome.
filter = (pred, [head, ...tail]) => { if (head === undefined) return []; if (pred(head)) { debugger; return [head, ...filter(pred, tail)]; } debugger; return [...filter(pred, tail)]; };
И ищем числа ≤ 10:
filter(x => x <= 10, [1, 10, 20]);
Поскольку [1, 10, 20]
нашего массива, head
- это первый элемент, 1, а tail
- это массив остальных: [10, 20]
.
Предикат проверяет, x
≤ 10, поэтому pred(1)
возвращает true
. Вот почему мы приостановили выражение debugger
в строке 4.
Поскольку текущий head
прошел проверку, ему разрешен вход в наш фильтрованный массив. Но мы еще не закончили, поэтому мы снова вызываем filter
с тем же предикатом, а теперь tail
.
Перейти к следующему debugger
.
Мы позвонили в filter
с [10, 20]
, поэтому head
теперь 10, а tail
[20]
. Так как же tail
становится меньше с каждой последующей итерацией?
Мы снова на строке 4 debugger
, потому что 10 ≤ 10. Переходим к следующей точке останова.
head
сейчас 20, а tail
пусто.
Начиная с 20 ›10, pred(head)
возвращает false
, и наш фильтрованный массив не будет включать его. Мы еще раз позвоним filter
без head
.
В следующий раз, однако, filter
выйдет из строя в строке 2. Разрушение пустого массива даст вам undefined
переменных. Пройдите мимо этой точки останова, чтобы получить возвращаемое значение.
Мне это кажется правильным!
Прокомментируйте, если это помогло. Следующим, вероятно, будет рекурсивный reduce
. 😁
Продолжайте кодировать. До скорого!
Береги себя,
Язид Бзадоу