JavaScript · Синтаксис · Проміжний

Методи масивів: map, filter, reduce

10 завдань

Функціональні методи масивів для перетворення, фільтрації та агрегації даних без явних циклів.

map, filter, reduce, forEach: неявний return та попередження про мутацію

#
**map — перетворити кожен елемент** ```javascript const nums = [1, 2, 3, 4]; // map повертає НОВИЙ масив — оригінал не змінює const doubled = nums.map(x => x * 2); // [2, 4, 6, 8] console.log(nums); // [1, 2, 3, 4] — незмінений // Callback map отримує (element, index, array): const tagged = nums.map((x, i) => `${i}:${x}`); // ['0:1', '1:2', '2:3', '3:4'] // Поширена помилка — забути неявний return в стрілочних функціях: const bad = nums.map(x => { x * 2 }); // [undefined, ...] — {} означає блок const good = nums.map(x => x * 2); // [2, 4, 6, 8] — вираз-тіло const good2 = nums.map(x => ({ value: x * 2 })); // об'єкт — загорни у () ``` **filter — залишити елементи, що проходять тест** ```javascript const evens = nums.filter(x => x % 2 === 0); // [2, 4] // filter теж повертає новий масив: const words = ['', 'hello', null, 'world', undefined]; const clean = words.filter(Boolean); // ['hello', 'world'] — видаляє хибні значення ``` **reduce — звернути до одного значення** ```javascript // reduce(callback, initialValue) // callback отримує (accumulator, currentValue, index, array) const sum = nums.reduce((acc, x) => acc + x, 0); // 10 const max = nums.reduce((acc, x) => x > acc ? x : acc, -Infinity); // 4 // Завжди надавай початкове значення — без нього reduce падає на порожньому масиві: [].reduce((acc, x) => acc + x); // TypeError: Reduce of empty array [].reduce((acc, x) => acc + x, 0); // 0 — безпечно ``` **forEach — лише побічні ефекти** ```javascript // forEach повертає undefined — ніколи не використовуй для побудови нового масиву nums.forEach(x => console.log(x)); // виводить 1 2 3 4 // ПОГАНО: const result = nums.forEach(x => x * 2); // undefined — не роби так // ДОБРЕ: використовуй map коли потрібен новий масив ``` **Попередження про мутацію: sort() та reverse() змінюють масив** ```javascript const arr = [3, 1, 4, 1, 5]; // sort і reverse МУТУЮТЬ оригінал: arr.sort((a, b) => a - b); // arr тепер [1, 1, 3, 4, 5] arr.reverse(); // arr тепер [5, 4, 3, 1, 1] // Сортувати без мутації (ES2023 toSorted/toReversed, або спочатку копіювати): const sorted = [...arr].sort((a, b) => a - b); // безпечно — spread копіює const rev = arr.toReversed(); // ES2023, повертає новий масив ```

Ланцюжки методів, reduce для групування, flatMap та Array.from

#
**Ланцюжки методів масиву** Оскільки map/filter повертають нові масиви, їх можна об'єднувати в ланцюжок: ```javascript const users = [ { name: 'Alice', age: 25, active: true }, { name: 'Bob', age: 17, active: true }, { name: 'Carol', age: 32, active: false }, { name: 'Dave', age: 28, active: true }, ]; const result = users .filter(u => u.active && u.age >= 18) // залишити активних повнолітніх .map(u => u.name) // отримати імена .sort(); // за алфавітом // ['Alice', 'Dave'] ``` **reduce для групування** ```javascript const orders = [ { category: 'food', amount: 30 }, { category: 'tech', amount: 200 }, { category: 'food', amount: 15 }, ]; const totals = orders.reduce((acc, order) => { acc[order.category] = (acc[order.category] ?? 0) + order.amount; return acc; }, {}); // { food: 45, tech: 200 } ``` **flatMap — відобразити, потім розгладити на один рівень** ```javascript const sentences = ['hello world', 'foo bar baz']; // map дає масив масивів: sentences.map(s => s.split(' ')); // [['hello','world'], ['foo','bar','baz']] // flatMap відображає, потім розгладжує на один рівень: sentences.flatMap(s => s.split(' ')); // ['hello', 'world', 'foo', 'bar', 'baz'] // flatMap також корисний для виводу змінної кількості елементів: const nums = [1, 2, 3]; nums.flatMap(x => x % 2 === 0 ? [x, x * 10] : [x]); // [1, 2, 20, 3] ``` **Array.from — створити масив з інших речей** ```javascript // З NodeList (DOM-елементи) Array.from(document.querySelectorAll('li')) .map(el => el.textContent); // З Set (дедублікація) const unique = Array.from(new Set([1, 2, 2, 3, 3])); // [1, 2, 3] // З рядка Array.from('hello'); // ['h', 'e', 'l', 'l', 'o'] // З функцією відображення (другий аргумент): Array.from({ length: 5 }, (_, i) => i * 2); // [0, 2, 4, 6, 8] ```

find/some/every, flat, довідник мутацій, includes vs indexOf

#
**find, findIndex, some, every** ```javascript const users = [ { id: 1, name: 'Alice', age: 25 }, { id: 2, name: 'Bob', age: 17 }, { id: 3, name: 'Carol', age: 32 }, ]; // find — перший збіг або undefined users.find(u => u.id === 2); // { id: 2, name: 'Bob', age: 17 } users.find(u => u.age > 50); // undefined // findIndex — індекс першого збігу або -1 users.findIndex(u => u.name === 'Carol'); // 2 // some — true якщо хоча б один збігається users.some(u => u.age < 18); // true (Бобу 17) // every — true якщо всі збігаються users.every(u => u.age >= 18); // false (Бобу 17) ``` **flat та flat(Infinity)** ```javascript const nested = [1, [2, 3], [4, [5, 6]]]; nested.flat(); // [1, 2, 3, 4, [5, 6]] — один рівень nested.flat(2); // [1, 2, 3, 4, 5, 6] — два рівні nested.flat(Infinity); // повне розгладжування, будь-яка глибина ``` **Довідник: мутація vs незмінність** ``` Метод Повертає новий масив? Мутує оригінал? ────────────── ───────────────────── ─────────────── map ✅ новий масив ❌ ні filter ✅ новий масив ❌ ні reduce ✅ одне значення ❌ ні flatMap ✅ новий масив ❌ ні flat ✅ новий масив ❌ ні slice ✅ новий масив ❌ ні concat ✅ новий масив ❌ ні sort ⚠ те саме посилання ✅ так — сортує на місці reverse ⚠ те саме посилання ✅ так — обертає на місці splice повертає вилучені ✅ так — змінює масив push/pop повертає елемент/довж. ✅ так shift/unshift повертає елемент/довж. ✅ так fill ⚠ те саме посилання ✅ так toSorted ✅ новий масив ❌ ні (ES2023) toReversed ✅ новий масив ❌ ні (ES2023) ``` **includes, indexOf, at** ```javascript [1, 2, 3].includes(2); // true [1, 2, NaN].includes(NaN); // true (на відміну від indexOf!) [1, 2, 3].indexOf(2); // 1 [1, 2, NaN].indexOf(NaN); // -1 (використовує ===, NaN !== NaN) // at() — підтримка від'ємного індексу const arr = [10, 20, 30, 40]; arr.at(-1); // 40 — останній елемент arr.at(-2); // 30 — передостанній ```
01

Подвоїти значення

#

Напишіть функцію, яка приймає масив чисел і повертає новий масив, де кожне число подвоєне. Використайте метод map().

function doubleValues(numbers) {

}

console.log(doubleValues([1, 2, 3, 4, 5]));
Рішення
function doubleValues(numbers) {
    return numbers.map(n => n * 2);
}

console.log(doubleValues([1, 2, 3, 4, 5]));
02

Залишити додатні

#

Напишіть функцію, яка приймає масив чисел і повертає лише додатні. Використайте метод filter().

function keepPositives(numbers) {

}

console.log(keepPositives([3, -1, 4, -1, -5, 9, -2, 6]));
Рішення
function keepPositives(numbers) {
    return numbers.filter(n => n > 0);
}

console.log(keepPositives([3, -1, 4, -1, -5, 9, -2, 6]));
03

Сума масиву

#

Напишіть функцію, яка приймає масив чисел і повертає їхню суму. Використайте метод reduce().

function sumArray(numbers) {

}

console.log(sumArray([1, 2, 3, 4, 5]));
Рішення
function sumArray(numbers) {
    return numbers.reduce((acc, n) => acc + n, 0);
}

console.log(sumArray([1, 2, 3, 4, 5]));
04

Слова довші за N

#

Напишіть функцію, яка приймає масив рядків і мінімальну довжину та повертає лише рядки, довші за цю довжину.

function longWords(words, minLength) {

}

console.log(longWords(["cat", "elephant", "dog", "hippopotamus"], 4));
Рішення
function longWords(words, minLength) {
    return words.filter(w => w.length > minLength);
}

console.log(longWords(["cat", "elephant", "dog", "hippopotamus"], 4));
05

Імена у верхньому регістрі

#

Напишіть функцію, яка приймає масив рядків і повертає новий масив, де кожен рядок переведено у верхній регістр.

function toUpperCase(words) {

}

console.log(toUpperCase(["hello", "world", "javascript"]));
Рішення
function toUpperCase(words) {
    return words.map(w => w.toUpperCase());
}

console.log(toUpperCase(["hello", "world", "javascript"]));
06

Добуток масиву

#

Напишіть функцію, яка приймає масив чисел і повертає добуток усіх елементів (перемножує всі разом). Використайте reduce().

function product(numbers) {

}

console.log(product([1, 2, 3, 4, 5]));
Рішення
function product(numbers) {
    return numbers.reduce((acc, n) => acc * n, 1);
}

console.log(product([1, 2, 3, 4, 5]));
07

Витягти властивість

#

Напишіть функцію, яка приймає масив об'єктів з властивістю `name` і повертає масив лише імен.

function getNames(people) {

}

const people = [
    { name: "Alice", age: 30 },
    { name: "Bob", age: 25 },
    { name: "Carol", age: 35 },
];
console.log(getNames(people));
Рішення
function getNames(people) {
    return people.map(p => p.name);
}

const people = [
    { name: "Alice", age: 30 },
    { name: "Bob", age: 25 },
    { name: "Carol", age: 35 },
];
console.log(getNames(people));
08

Ланцюжок: filter потім map

#

Напишіть функцію, яка приймає масив чисел, залишає лише ті, що більші за 10, і повертає квадрати решти чисел.

function squaresAboveTen(numbers) {

}

console.log(squaresAboveTen([3, 15, 8, 20, 5, 12]));
Рішення
function squaresAboveTen(numbers) {
    return numbers
        .filter(n => n > 10)
        .map(n => n ** 2);
}

console.log(squaresAboveTen([3, 15, 8, 20, 5, 12]));
09

Підрахунок за умовою

#

Напишіть функцію, яка приймає масив чисел і повертає кількість парних серед них.

function countEven(numbers) {

}

console.log(countEven([1, 2, 3, 4, 5, 6, 7, 8]));
Рішення
function countEven(numbers) {
    return numbers.filter(n => n % 2 === 0).length;
}

console.log(countEven([1, 2, 3, 4, 5, 6, 7, 8]));
10

Групування за першою літерою

#

Напишіть функцію, яка приймає масив рядків і повертає об'єкт, де кожен ключ — перша літера, а значення — масив усіх слів, що починаються з цієї літери.

function groupByFirstLetter(words) {

}

const result = groupByFirstLetter(["apple", "banana", "avocado", "blueberry", "cherry"]);
console.log(result);
Рішення
function groupByFirstLetter(words) {
    return words.reduce((acc, word) => {
        const letter = word[0];
        if (!acc[letter]) acc[letter] = [];
        acc[letter].push(word);
        return acc;
    }, {});
}

const result = groupByFirstLetter(["apple", "banana", "avocado", "blueberry", "cherry"]);
console.log(result);