Top view of cat working on computer. Funny photo of cat paws typing, texting or pressing buttons on a laptop keyboard. High quality photo
Зазвичай кажуть, що reduce()
у JS використовується для згортки масивів. Це визначення надто розмите, тому ми спробуємо його пояснити.
Метод reduce()
зводить масив до єдиного значення, тобто редукуючи (скорочуючи) його. Він відноситься до групи методів, що використовуються для перебирання значень масиву, доповнюючи такі методи як forEach
, filter
, map
і every/some
.
Метод reduce()
по черзі перебирає значення елементів масиву, зберігаючи проміжний результат своєї обробки. Цей інструмент може бути складним чи нецікавим, але насправді ясне розуміння принципу його роботи істотно скорочує вирішення багатьох завдань.
Array.reduce()
як параметр задіює метод функції зворотного виклику, який використовується для перебору кожного елемента в масиві, а також аргументи акумулятора ( total
) та вихідне значення initialValue
.
До початку перебору, значення, що обчислюється (якщо ми не визначимо його самостійно) дорівнює нульовому елементу масиву:
array.reduce(functioncallback(total, currentValue, currentIndex, array), initialValue)
Наступний параметр functioncallback
— currentValue
кожен наступний елемент масиву. Далі два необов’язкових параметри: index
— номер елемента в масиві, який обробляється, а також array
— масив, з яким працює reduce()
.
Останній параметр використовується вкрай рідко (у тих випадках, коли масив мутується) — так найчастіше ми маємо доступ до масиву за якоюсь змінною.
Розглянемо роботу методу reduce()
на прикладі обчислення суми значень елементів масиву. Припустимо, ми працюємо з масивом товарів і ставимо за мету підрахувати вартість усіх найменувань:
const products_items = [ { title: "Processor Intel Core i7", price: 200 }, { title: "laptop MSI CX70", price: 700 }, { title: "TV-box", price: 150 }, { title: "Desktop", price: 2500 } ]; const totalPrice = products_items.reduce((acc, products_items, i, arr) => { console.log(acc) return acc + products_items.price; }, 0); console.log('Сумарна вартість усіх позицій -', totalPrice);
Зверніть увагу: початкове значення акумулятора ми встановлюємо вручну — це нуль. На екрані ми побачимо результат кожної ітерації, а також кінцеву суму всіх значень:
0 200 900 1050 Сумарна вартість усіх позицій - 3550
Функція reduce()
дозволить просто перебрати елементи масиву, звівши його до середнього значення всіх елементів:
// Заданий набір чисел, що треба опрацювати const massiv_chisel = [1, 2, 3, 4, 37, 47, 23, 17]; const srednee = (massiv_chisel) =>{ const total = massiv_chisel.reduce((total, number) => { return total + number; // Підрахунок всіх элементів масиву }, 0); // Первинне значення не забуваємо визначити рівним 0 //Обчислення середнього значення як відношення суми елементів до довжини масиву return total / massiv_chisel.length; } console.log(srednee(massiv_chisel)); //відображення результата на экрані
Результат обчислень:
16,75
Інструмент reduce()
у деяких випадках значно спрощує код і робить його компактнішим.
Наприклад, уявіть собі, що у вас є масив товарів різної властивості, наприклад флешки об’ємом 128 Гб, 512 Гб і 256 Гб. Вам потрібно створити новий масив, який міститиме імена тих виробників, чиї флешки є на 512 Гб.
Для вирішення цього завдання ми застосуємо фільтр, який відсіюватиме з даного масиву значення, що задовольняють умові — ємність USB-носія дорівнює 512, а потім застосуємо метод Array.map()
, який створить нам новий масив, що містить тільки список імен виробників.
const USB_drives = [ { vendor: 'Samsung', Flash_Drive_Capacity: 128 }, { vendor: 'Goodram', Flash_Drive_Capacity: 512 }, { vendor: 'Apacer', Flash_Drive_Capacity: 32 }, { vendor: 'SanDisk', Flash_Drive_Capacity: 512 }, { vendor: 'Verbatim', Flash_Drive_Capacity: 512 }, { vendor: 'Transcend', Flash_Drive_Capacity: 256 }, { vendor: 'Kingston', Flash_Drive_Capacity: 256 }]; const vendors = USB_drives.filter(function (assembly) { return assembly.Flash_Drive_Capacity === 512; }).map(function (assembly) { return assembly.vendor; }); console.log(vendors);
У консолі ми побачимо результат обробки масиву:
[ 'Goodram', 'SanDisk', 'Verbatim' ]
З використанням reduce()
це завдання вирішується простіше. Ми можемо відмовитися від комбінації методів Array.map()
та Array.filter()
.
Застосування методу Array.reduce()
дає можливість збільшити продуктивність коду, оскільки в цьому випадку відбувається перебір елементів масиву одним проходом.
const vendors = USB_drives.reduce(function (newArr, assembly) { if (assembly.Flash_Drive_Capacity === 512) { newArr.push(assembly.vendor); } return newArr; }, []); console.log(vendors);
Розглянемо інший приклад — коли потрібно об’єднати два масиви в один. Допустимо у нас є перелік тих же USB-накопичувачів із зазначенням виробника та ємності.
const USB_drives = [ { vendor: 'Samsung Group', Flash_Drive_Capacity: 128 }, { vendor: 'Goodram', Flash_Drive_Capacity: 512 }, { vendor: 'Apacer', Flash_Drive_Capacity: 32 }, { vendor: 'Western Digital', Flash_Drive_Capacity: 512 }, { vendor: 'Verbatim Corp', Flash_Drive_Capacity: 512 }, { vendor: 'Transcend', Flash_Drive_Capacity: 256 }, { vendor: 'Kingston', Flash_Drive_Capacity: 256 }];
Другий масив даних – це дані про швидкість читання пристроїв.
const speed = { SamsungGroup: 150, WesternDigital: 75, Apacer: 100, VerbatimCorp: 270 };
Спробуємо об’єднати їх в єдиний масив, де позиції, для яких не вказано швидкість читання, матимуть прочерк.
const specification_with_speed = USB_drives.reduce(function (arr, assembly) { // Отримуємо значення для об'єкта speed, видаливши прогалини з імені вендора const key = assembly.vendor.replace(' ', ''); // Якщо для позиції є значення – додаємо його // Інакше ставимо прочерк. if (speed[key]) { assembly.speed = speed[key]; } else { assembly.speed = '-'; } // Додаємо об'єкт assembly arr.push(assembly); // Повертаємо масив return arr; }, []); // Виводимо на екран результат console.log(specification_with_speed);
У результаті отримуємо:
{ vendor: 'Samsung Group', Flash_Drive_Capacity: 128, speed: 150 }, { vendor: 'Goodram', Flash_Drive_Capacity: 512, speed: '-' }, { vendor: 'Apacer', Flash_Drive_Capacity: 32, speed: 100 }, { vendor: 'Western Digital', Flash_Drive_Capacity: 512, speed: 75 }, { vendor: 'Verbatim Corp', Flash_Drive_Capacity: 512, speed: 270 }, { vendor: 'Transcend', Flash_Drive_Capacity: 256, speed: '-' }, { vendor: 'Kingston', Flash_Drive_Capacity: 256, speed: '-' }
Метод Array.reduce()
дозволяє вирішити й інше завдання — коли дані з двох масивів необхідно перетворити на об’єкт.
Наприклад, назва фірми-виробника — це буде ключ, а обсяг накопичувача та його швидкість — це властивості.
const USB_drives = [ { vendor: 'Transcend', USB_capacity: 512 }, { vendor: 'GOODRAM', USB_capacity: 128 }, { vendor: 'Samsung', USB_capacity: 256 }, { vendor: 'Apacer', USB_capacity: 64 }, { vendor: 'Western Digital', USB_capacity: 128 } ]; const speed = { Samsung: 100, Transcend: 50, Apacer: 120, WesternDigital: 121 }; const USB_drivesAsAnObject = USB_drives.reduce(function (obj, usb) { // Видаляємо пробіл в назві вендора const key = usb.vendor.replace(' ', ''); // Якщо носій має відомості про швидкість, додамо їх // Інакше присвоїми нуль if (speed[key]) { usb.speed = speed[key]; } else { usb.speed = 0; } // Видаляємо властивість vendor delete usb.vendor; // Добавляємо usb дані в новий об'єкт obj[key] = usb; // Повертаємо масив return obj; }, {}); console.log(USB_drivesAsAnObject);
Відображення результату в консолі:
{ Transcend: { USB_capacity: 512, speed: 50 }, GOODRAM: { USB_capacity: 128, speed: 0 }, Samsung: { USB_capacity: 256, speed: 100 }, Apacer: { USB_capacity: 64, speed: 120 }, WesternDigital: { USB_capacity: 128, speed: 121 } }
Припустимо, ми маємо три документи. Кожен із них містить свій текстовий фрагмент, свого автора та свою дату створення. На основі цих трьох документів ми повинні створити новий масив, де записані автори усіх документів, об’єднати вміст документів і вказати найновішу дату створення з існуючих дат.
Знову ж таки скористаємося методом reduce()
:
const documents = [{ text: "Варкалось, хливкі шорькі пирялися по наві", author: "Доджсон", date: "1865-02-17 05:12:11" }, { text: "Та хрюкотали зелюки", author: "Льюіс", date: "1853-03-07 02:22:14" }, { text: "Як мюмзіки в мовє", author: "Керрол", date: "1845-12-11 15:02:44" }]; const summaryDocuments = (documents) => { return documents.reduce((generalDocument, document) =>{ generalDocument.text = generalDocument.text + " " + document.text; generalDocument.authors.push(document.author); if (!generalDocument.date || new Date(generalDocument.date).valueOf() <= new Date(document.date)){ generalDocument.date = document.date; } return generalDocument; }, { text: "", authors: [], date: null }); } console.log(summaryDocuments(documents));
Результат склеювання документів відображається на екрані:
{ text: ' Варкалось, хливкі шорькі пирялися по наві Та хрюкотали зелюки Як мюмзіки в мовє', authors: [ 'Доджсон', 'Льюіс', 'Керрол' ], date: '1865-02-17 05:12:11' }
Бібліотека lodash
дозволяє використовувати для згрупування колекції елементів за заданими критеріями. Наприклад, коли необхідно впорядкувати елементи за цілим числом, застосовується наступний метод:
const _ = require('lodash'); //підключаємо всі методи бібліотеки chisla = [7.1, 4.1, 1.3, 7.987, 2.5, 4.76]; //набір елементів console.log(chisla); //виведення в консоль вихідного набору чисел console.log(_.groupBy(chisla, Math.floor)); //виведення з угрупованням за цілочисленним значенням
Результат на екрані:
[ 7.1, 4.1, 1.3, 7.987, 2.5, 4.76 ] { '1': [ 1.3 ], '2': [ 2.5 ], '4': [ 4.1, 4.76 ], '7': [ 7.1, 7.987 ] }
Масив слів також можна відсортувати за довжиною рядкових даних:
const slova = ['winter', 'cat', 'bot', 'snow', 'father']; //набір елементів console.log(slova); console.log(_.groupBy(slova, 'length'));
Відображення в консолі:
[ 'winter', 'cat', 'bot', 'snow', 'father' ] { '3': [ 'cat', 'bot' ], '4': [ 'snow' ], '6': [ 'winter', 'father' ] }
Цю функціональність можна реалізувати і без бібліотеки lodash
— за допомогою Array.reduce()
. Напишемо функцію, аргументами якої будуть масив та критерії сортування. Усередині цієї функції ми будемо передавати порожній об’єкт і повертати результат:
const arr = [7.1, 4.1, 1.3, 7.987, 2.5, 4.76]; const slova = ['winter', 'cat', 'bot', 'snow', 'father']; const groupBy = function (arr, criteria) { return arr.reduce(function (obj, item) { //Перевірка - чи є критерій угруповання функцією чи властивістю елемента const key = typeof criteria === 'function' ? criteria(item) : item[criteria]; // Якщо властивість не створено, створюємо її. if (!obj.hasOwnProperty(key)) { obj[key] = []; } // Поміщаємо значення в об'єкт obj[key].push(item); // Повернення об'єкта для нової ітерації return obj; }, {});}; console.log(groupBy(arr, Math.floor)); console.log(groupBy(slova, 'length'));
Сподіваємося, що описані вище приклади допомогли вам чіткіше відчути переваги reduce()
при вирішенні різних завдань JavaScript.
Для закріплення матеріалу рекомендуємо подивитися відео з розбором різних завдань, де потрібно застосувати функцію reduce()
:
Резиденти Дія.City сплатили до бюджету понад 8 млрд грн податків в І кварталі 2025 року.…
У Китаї закликають офісних працівників не працювати надто багато — держава сподівається, що вільний час…
Експерти звертають увагу на тривожну тенденцію: люди все частіше використовують ChatGPT, щоб визначити місцезнаходження, зображене…
Компанія JetBrains випустила нову версію мультимовного середовища розробки IntelliJ IDEA 2025.1. Оновлена IDE отримала численні…
Платформа обміну миттєвими повідомленнями Discord впроваджує функцію перевірки віку за допомогою сканування обличчя. Зараз вона…
Wikipedia намагається захистити себе від тисяч різноманітних ботів-скрейперів, які сканують дані цієї платформи для навчання…