Lab / JavaScript

JavaScript: Понимание функции Reduce()

Функия reduce одна из наиболее важных в данном цикле статей. С её помощью вы можете добиться невероятных результатов сэкономив десятки строк кода.

Содержимое мини-курса:

Определение и синтаксис

Метод reduce() используется для применения функции к каждому элементу массива, чтобы уменьшить (свернуть) массив до одного искомого значения.

Вот как выглядит синтаксис:

let result = arr.reduce(callback);
// Optionally, you can specify an initial value
let result = arr.reduce(callback, initValue);

Наша функция обратного вызова 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().