„Последната ми публикация“ обхваща рекурсивно 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 става по-малък с всяка следваща итерация?

Отново сме на debugger на ред 4, защото защото 10 ≤ 10. Преминете към следващата точка на прекъсване.

head вече е 20, а tail е празен.

Тъй като 20 › 10, pred(head) връща false и нашият филтриран масив няма да го включва. Ще се обадим на filter още веднъж без head.

Този следващ път обаче filter ще се спаси на ред 2. Деструктурирането на празен масив ви дава undefined променливи. Продължете след тази точка на прекъсване, за да получите върнатата стойност.

Това ми изглежда правилно!

Помислете за коментиране, ако това е помогнало. Рекурсивният reduce вероятно е следващият. 😁

Продължете да кодирате. До следващия път!

Пази се,
Yazeed Bzadough