JavaScript: Понимание функции Reduce()
Функия reduce одна из наиболее важных в данном цикле статей. С её помощью вы можете добиться невероятных результатов сэкономив десятки строк кода.
Содержимое мини-курса:
- Функция Map()
- Функция Filter()
- Функция Reduce()
Вы здесь
- Выполнение цепочки, Map(), Filter(), Reduce() вместе
Определение и синтаксис
Метод reduce()
используется для применения функции к каждому элементу массива, чтобы уменьшить (свернуть) массив до одного искомого значения.
Вот как выглядит синтаксис:
let result = arr.reduce(callback);
// Optionally, you can specify an initial value
let result = arr.reduce(callback, initValue);
result
— единственное значение которое вернёт функцияarr
— массив данных который мы обрабатывемcallback
— функция, выполняемая для каждого элемента массива.initValue
— необязательное начальное значение. Если это значение не задано, в качестве используется 0-й элемент.
Наша функция обратного вызова callback()
может принимать четыре аргумента. Вы уже знакомы с тремя аргументами из методов map()
и filter()
из наших предыдущих статей миникурса. Новым для вас будет лишь аргумент accumulator
.
accumulator
— Аккумулятор накапливает все возвращаемые значения обратных вызовов.
val
— текущее обрабатываемое значение
index
— текущий индекс обрабатываемого значения
arr
— исходный массив
Reduce vs. For
Вы можете предстваить себе метод работы функции filter()
на примере цикла for
, который использует элементы массива для создания чего-то нового. Рассмотрим на примере следующего кода:
var arr = [1, 2, 3, 4];
var sum = 0;
for(var i = 0; i < arr.length; i++) {
sum += arr[i];
}
// sum = 10
Цель вышеуказанного кода — найти сумму всех значений в нашем массиве. Он проходит по массиву и прибавляет каждое значение к переменной по одному. Когда это цикл завершится, наша сумма будет равна 10.
Хотя приведённый код прекрасно справился с задачей, существует гораздо более простой способ добиться аналогичного результата — с помощью функции reduce()
.
Чтобы реализовать эту же задачк, используя функцию reduce()
, мы начнем с того же простого массива чисел let arr = [1,2,3,4]
.
arr
— это массив, который мы собираемся свернуть. Наша задача — найти сумму всех чисел в нашем массиве. Чтобы сделать это, каждая итерация прибавит текущее значение к нашему аккумулятору и вернет его.
let sum = arr.reduce((acc, val) => {
return acc + val;
});
Мы использовали переменную acc
для объявления нашего аккумулятора. Поскольку наша функция reduce()
работает через массив arr
, значение acc
будет увеличиваться до завершения цикла функции.
После исполнения кода мы можем вывести нашу переменную sum и увидеть, что функция работает:
console.log(sum)
//sum = 10
Определение начального значения
Помните ранее я указал, что у нас так-же имеется необязательное начальное значение? Его очень легко задать. Давайте снова используем тот же пример, что и выше. Мы собираемся скложить значения нашего массива, но на этот раз мы хотим начать со страртового значения 100.
let sum = arr.reduce((acc, val) => {
return acc + val;
}, 100);
Как вы наверное уже заметили, приведенный выше код практически идентичен предыдущему примеру. Мы всего лиш добавили второй аргумент после нашего обратного вызова. Только на этот раз мы установили значение 100 в качестве отправной точки.
ES6 и уменьшение кода
Синтаксис со стрелочными функциями позволяет нам еще больше упростить код. Когда вы делаете return
в стрелочной функции, можно опустить скобки и ключевое слово return, чтобы указать, что вы возвращаете значение.
let sum = arr.reduce((acc, val) => acc + val, 100);
Удобно, не так ли? Всего одной строкой кода мы можем взять число например 100 и добавить его к сумме целого массива!
Усложним пример
Подготовим вот такие данные:
let data = [
{
country: 'China',
pop: 1409517397,
},
{
country: 'India',
pop: 1339180127,
},
{
country: 'USA',
pop: 324459463,
},
{
country: 'Indonesia',
pop: 263991379,
}
]
Давайте решим вот такую задачку, нам нужно подсчитать население вышеперечисленных стран, но исклчить из подсчёта жителей Китая.
let sum = data.reduce((acc, val) => {
return val.country == 'China' ? acc : acc + val.pop;
}, 0);
Я использовал 0 как начальное значение. Затем на каждой итерации проверяю, соответствует ли название страны текущей итерации «Китайю», если соответствует — возвращаю acc
без изменений. Таким образом я выполняю суммирование населения всех стран, как в примере выше, только перебирая объекты и игнорирую Китай.
После отработки функции мы долнжны получить сумму sum = 1927630969
. Вот так вот просто можно ворочать больими коллекциями данных с помошью всего пары строк через функцию Reduce()
.