Поскольку год начинается, я решил сделать серию статей, которые объясняют различные API (интерфейсы по программированию приложений) на языке JavaScript. В каждой статье мы распустим обычно используемую функцию в JavaScript и попробуйте пройти различные приложения.
Первая функция, которую мы будем проходить, это « » Уменьшить Функция более высокого порядка. Это в основном потому, что из всех методов Array JS потребовалось мне немного времени, чтобы понять, как работает функция уменьшения.
Эта статья предполагает, что читатель понимает другие методы массива, такие как карта и Фильтр Потому что это поможет в понимании того, как Уменьшить работает.
Для того, чтобы полностью понять идею уменьшить , Мы рассмотрим несколько примеров простых решений, использующих для петли, а затем реализуйте те же решения, используя уменьшение функция. Тогда мы посмотрим на некоторые более продвинутые случаи использования для уменьшения функция.
Пример 1.
Первым примером мы рассмотрим, является общим: расчет суммы предметов в массиве. Это требует простого решения, а использование для петля должна выглядеть так:
const arrayItems = [1,2,3,4,5,6];
let sum = 0;
for (let i = 0; i < arrayItems.length; i++) {
sum = sum + arrayItems[i];
}
// sum = 21Раствор выше довольно прост, где мы добавляем каждый элемент в массиве и храните результат в сумма Переменная. Таким образом, следующий шаг – реализовать одно и то же решение, используя Уменьшить , который должен выглядеть как код ниже:
const arrayItems = [1,2,3,4,5,6];
const sum = arrayItems.reduce(function(accumulator, currentItemInArray){
accumulator = accumulator + currentItemInArray;
return accumulator;
}, 0);
// sum = 21Глядя на два примера выше, довольно очевидно, что для Пример петли кажется проще, и это было причиной некоторых аргументов в экосистеме. Но этот пример является переплетением, и мы используем только его, чтобы легко понять, как уменьшить Функция работает, поэтому давайте поработаем через пример.
Нам нужно, прежде всего, понять, что такое функция уменьшения. Это метод, который существует для каждого массива JavaScript. Это позволяет нам петлю через каждый элемент в массиве и выполнять функцию на каждом из этих элементов.
Это довольно похоже на поведение Карта Функция, но она имеет поворот – это позволяет нам вернуть любое значение из нашей функции в определенной итерации, которая затем существует в качестве параметра (аргумента) в этой функции в следующем итерации (это значение обычно известно как Аккумулятор ).
Объяснить дальше, уменьшить Функция занимает 2 аргумента:
- Функция обратного вызова: это функция, которая обычно содержит 4 параметра. Но сейчас нас беспокоит только первый, аккумулятор, а второй, который является текущим элементом в массиве во время этой итерации.
- Исходное значение: это начальное значение аккумулятора при запуске итерации. В примере выше значения равно 0, что означает начальное значение аккумулятора будет 0.
Вернуться к нашему примеру:
const arrayItems = [1,2,3,4,5,6];
const sum = arrayItems.reduce(function(accumulator, currentItemInArray){
accumulator = accumulator + currentItemInArray;
return accumulator;
}, 0);
// sum = 21Это может быть дополнительно разбито в функцию обратного вызова и начальное значение:
const arrayItems = [1,2,3,4,5,6];
function callbackFunction(accumulator, currentItemInArray){
accumulator = accumulator + currentItemInArray;
return accumulator;
}
const initialValue = 0;
const sum = arrayItems.reduce(callbackFunction, initialValue);
// sum = 21Сложная часть для меня была понять, как работает аккумулятор. Чтобы объяснить это, мы пройдемся через каждую итерацию в петле.
Итерация 1.
В первой итерации, поскольку наше начальное значение равно 0, наш аккумулятор будет иметь значение 0. Так что наша функция будет выглядеть так:
const arrayItems = [1,2,3,4,5,6];
// 1 is the current item in the array
function callbackFunction(accumulator = 0, currentItemInArray = 1){
accumulator = 0 + 1;
return accumulator // which is 1;
}callbackfunction вернет значение 1. Это будет автоматически использоваться в качестве следующего значения для аккумулятора во второй итерации.
Итерация 2.
const arrayItems = [1,2,3,4,5,6];
// 2 is the current item in the array
function callbackFunction(accumulator = 1, currentItemInArray = 2){
accumulator = 1 + 2;
return accumulator // which is 3;
}В этой итерации наш аккумулятор будет иметь значение 1, которое было возвращено в нашей первой итерации. callbackfunction вернет значение 3 в этой итерации. Это означает, что наш аккумулятор будет иметь значение 3 в нашей третьей итерации.
Итерация 3.
const arrayItems = [1,2,3,4,5,6];
// 3 is the current item in the array
function callbackFunction(accumulator = 3, currentItemInArray = 3){
accumulator = 3 + 3;
return accumulator // which is 6;
}В третьей итерации наш аккумулятор будет иметь значение 3, которое было возвращено callbackfunction в итерации 2. callbackfunction вернет значение 6, которое будет использоваться в качестве значения аккумулятора в итерации 4. Эти шаги будут повторяться, пока не доберемся до последнего элемента в массиве, который составляет 6.
Как я уже упоминал ранее, пример выше может быть сверхуличным, поэтому давайте посмотрим на проблему, где используя уменьшение чаще всего (Тем не менее, это не значит, что a для петля не может использоваться для реализации рабочего решения).
Пример 2.
Второй пример включает подсчет количества вхождений каждого элемента в массиве, например:
//Given an input
const fruits = ['apples', 'apples', 'bananas', 'oranges', 'apples', 'oranges', 'bananas', 'grapes'];
// should give an output of
const count = { 'apples': 3,'oranges': 2,'bananas': 2, 'grapes': 1 };Давайте реализуем решение, затем пройдите каждую итерацию и посмотрим, что происходит:
const fruits = ['apples', 'apples', 'bananas', 'oranges', 'apples', 'oranges', 'bananas', 'grapes'];
function countOccurrence(accumulator, currentFruit){
const currentFruitCount = accumulator[currentFruit];
// if the fruit exists as a key in the object, increment its value, else add the fruit as a key to the object with a value of 1
if(currentFruitCount) {
accumulator[currentFruit] = currentFruitCount + 1;
} else {
accumulator[currentFruit] = 1
}
return accumulator;
}
const initialValue = {};
const count = fruits.reduce(countOccurrence, initialValue);Решение написано, чтобы быть максимально возможной, чтобы мы могли понять, что происходит в коде. Как мы сделали раньше, давайте пройдемся через первые несколько итераций.
Итерация 1.
В первой итерации, поскольку мы сделали наше начальное значение пустым объектом, значением Аккумулятор будет пустой объект. Это означает, что CountoCurrence Функция будет выглядеть как код ниже, когда его называется:
const fruits = ['apples', 'apples', 'bananas', 'oranges', 'apples', 'oranges', 'bananas', 'grapes'];
// current element is 'apples'
function countOccurrence(accumulator = {}, currentFruit = 'apples'){
// since currentFruit = 'apples' then accumulator[currentFruit] = accumulator['apples']
const currentFruitCount = accumulator[currentFruit];
// currentFruitCount will be null since accumulator is an empty object
if(currentFruitCount) {
accumulator[currentFruit] = currentFruitCount + 1;
} else {
// this block will run since accumulator is empty
// currentFruit = 'apples'
accumulator['apples'] = 1
// accumulator should look like this: { 'apples': 1 }
}
return accumulator // which is { 'apples': 1 };
}С аккумулятор пустой объект, currentfruitcount будет нулевой . Это означает, что еще Блок будет работать там, где новый ключ (яблоки) со значением 1 будет добавлен к аккумулятор . Это будет возвращено из функции, которая будет передана как значение аккумулятора во второй итерации.
Итерация 2.
Во второй итерации наш Аккумулятор будет иметь значение {«Яблоки»: 1} , который был возвращен CUCCOCCURRENCE функция в первой итерации. Тогда CUCCOCCURRENCE Функция будет выглядеть как код ниже:
const fruits = ['apples', 'apples', 'bananas', 'oranges', 'apples', 'oranges', 'bananas', 'grapes'];
// current element is 'apples'
function countOccurrence(accumulator = { 'apples': 1 }, currentFruit = 'apples'){
// since currentFruit = 'apples' then accumulator[currentFruit] = accumulator['apples']
const currentFruitCount = accumulator[currentFruit];
// currentFruitCount will be 1
if(currentFruitCount) {
// this block will run since currentFruitCount is 1
// currentFruit = 'apples'
accumulator['apples'] = 1 + 1;
// accumulator should look like this: { 'apples': 2 }
} else {
accumulator[currentFruit] = 1
}
return accumulator // which is { 'apples': 2 };
}С Аккумулятор Содержит ключ («Apple») со значением 1, Towerfruit будет 1, что означает Если Блок будет запущен. В этом блокируйте значение яблоко Ключ будет увеличиваться на 1 сделать его 2, и это новое значение будет обновлено в объекте аккумулятора, чтобы сделать его {«Яблоки»: 2} Отказ Это значение будет возвращено CUCCOCCURRENCE Функция и передается как значение для аккумулятора в третьей итерации.
Итерация 3.
Для нашей третьей итерации Аккумулятор имеет значение {яблоки: 2} который был возвращен Countoccurence во время второй итерации. Countoccurence Функция будет выглядеть как код ниже:
const fruits = ['apples', 'apples', 'bananas', 'oranges', 'apples', 'oranges', 'bananas', 'grapes'];
// current element is 'bananas'
function countOccurrence(accumulator = { 'apples': 2 }, currentFruit = 'bananas'){
// since currentFruit = 'bananas' then accumulator[currentFruit] = accumulator['bananas']
const currentFruitCount = accumulator[currentFruit];
// currentFruitCount will be null since accumulator doesn't contain 'bananas'
if(currentFruitCount) {
accumulator[currentFruit] = currentFruitCount + 1;
} else {
// this block will run since currentFruitCount is null
// currentFruit = 'bananas'
accumulator['bananas'] = 1
}
return accumulator // which is { 'apples': 2, 'bananas': 1 };
}Эта итерация похожа на первую – с Бананы не существует в аккумулятор Он будет добавлен к объекту и учитывая ценность 1 делать аккумулятор Похоже, {«Яблоки»: 2, «Бананы»: 1} Отказ Это тогда станет ценностью Аккумулятор для четвертой итерации.
Процесс повторит себя до уменьшения Функция имеет итерацию через каждый элемент в массиве.
Упаковка
Я действительно надеюсь, что эти примеры были достаточно ясны, чтобы создать ментальную модель того, как Уменьшить Функция работает.
Если вы читаете это, и вы хотите увидеть более продвинутые примеры (например, внедрение функции Pipe Функция) Не стесняйтесь твитнуть на меня, и я отвечу, как только смогу. Кроме того, если у вас есть другие примеры, я бы хотел увидеть их. Спасибо!!!
Оригинал: “https://www.freecodecamp.org/news/applications-of-the-reduce-function-in-javascript/”