Функция сокращения может выполнять такие операции, как накопление, фильтрация, группировка, сопоставление и т. д. по мере необходимости, и является очень мощным методом массива. Он очень часто используется при обработке данных. Многие сложные логики очень просты, если они обрабатываются с помощью сокращения. В процессе фактической разработки были накоплены некоторые общие и очень полезные фрагменты кода методов сокращения, и для справки вы можете выбрать следующие 10.

Уменьшить введение

reduceЭто метод массива, который может выполнять функцию обратного вызова для каждого элемента в массиве по очереди и вычислять окончательное значение последовательно слева направо. Его синтаксис:

arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

Среди них callback — функция обратного вызова, выполняемая каждым элементом, которая содержит 4 параметра:

  • accumulator: Аккумулятор, который является возвращаемым значением последнего выполнения функции обратного вызова.
  • currentValue: значение текущего элемента.
  • index: нижний индекс текущего элемента.
  • array: исходный массив.

initialValue является необязательным и представляет начальное значение аккумулятора.

reduceВыполнение функции выглядит следующим образом:

  1. Если не указано initialValue, первый элемент массива используется как начальное значение аккумулятора, в противном случае начальное значение аккумулятора равно initialValueused.
  2. Выполняет функцию обратного вызова для каждого элемента массива по очереди, начиная со второго элемента массива.
  3. Возвращаемое значение функции обратного вызова используется как значение аккумулятора при следующем выполнении функции обратного вызова.
  4. После того, как функция обратного вызова выполняется для каждого элемента массива, reduceфункция возвращает возвращаемое значение последней функции обратного вызова, которое является окончательным совокупным значением.

Подсчитайте количество вхождений каждого элемента в массиве

const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((accumulator, currentValue) => {
  accumulator[currentValue] = (accumulator[currentValue] || 0) + 1;
  return accumulator;
}, {});
console.log(count); // Output: { apple: 3, banana: 2, orange: 1 }

Сведение вложенных массивов

const nestedArray = [[1, 2], [3, 4], [5, 6]];
const flattenedArray = nestedArray.reduce((accumulator, currentValue) => accumulator.concat(currentValue), []);
console.log(flattenedArray); // Output: [1, 2, 3, 4, 5, 6]

Сгруппировать по условию

const people = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 },
  { name: 'David', age: 25 },
  { name: 'Emily', age: 30 }
];
const groupedPeople = people.reduce((accumulator, currentValue) => {
  const key = currentValue.age;
  if (!accumulator[key]) {
    accumulator[key] = [];
  }
  accumulator[key].push(currentValue);
  return accumulator;
}, {});
console.log(groupedPeople);
// Output: {
//   25: [{ name: 'Alice', age: 25 }, { name: 'David', age: 25 }],
//   30: [{ name: 'Bob', age: 30 }, { name: 'Emily', age: 30 }],
//   35: [{ name: 'Charlie', age: 35 }]
// }

Объединить несколько массивов в один объект

const keys = ['name', 'age', 'gender'];
const values = ['Alice', 25, 'female'];
const person = keys.reduce((accumulator, currentValue, index) => {
    accumulator[currentValue] = values[index];
    return accumulator;
  }, {});
console.log(person); // Output: { name: 'Alice', age: 25, gender: 'female' }

Преобразование строки в объект

const str = 'key1=value1&key2=value2&key3=value3';
const obj = str.split('&').reduce((accumulator, currentValue) => {
  const [key, value] = currentValue.split('=');
  accumulator[key] = value;
  return accumulator;
}, {});
console.log(obj); 
// Output: { key1: 'value1', key2: 'value2', key3: 'value3' }

Преобразование объекта в строку запроса

const params = { foo: "bar", baz: 42 };
const queryString = Object.entries(params).reduce((acc, [key, value]) => {
  return `${acc}${key}=${value}&`;
}, "?").slice(0, -1);
console.log(queryString); // "?foo=bar&baz=42"

Распечатайте последовательность Фибоначчи

const fibonacci = n => {
  return [...Array(n)].reduce((accumulator, currentValue, index) => {
    if (index < 2) {
      accumulator.push(index);
    } else {
      accumulator.push(accumulator[index - 1] + accumulator[index - 2]);
    }
    return accumulator;
  }, []);
};
console.log(fibonacci(10)); // Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Проверяет, является ли строка палиндромом

const str = 'racecar';
const isPalindrome = str.split('').reduce((accumulator, currentValue, index, array) => {
  return accumulator && currentValue === array[array.length - index - 1];
}, true);
console.log(isPalindrome); // Output: true

Проверяет совпадение скобок

const str = "(()()())";
const balanced = str.split("").reduce((acc, cur) => {
  if (cur === "(") {
    acc++;
  } else if (cur === ")") {
    acc--;
  }
  return acc;
}, 0) === 0;
console.log(balanced); // true

Получить свойства объекта рекурсивно

const user = {
  info: {
    name: "Jason",
    address: { home: "Shaanxi", company: "Xian" },
  },
};
function get(config, path, defaultVal) {
  return path.split('.').reduce((config, name) => config[name], config) || defaultVal;
  return fallback;
}
get(user, "info.name"); // Jason
get(user, "info.address.home"); // Shaanxi
get(user, "info.address.company"); // Xian
get(user, "info.address.abc", "default"); // default

Рукописное сокращение

Вы можете лучше понять, как это работает, написав простую reducefunction:

function myReduce(arr, callback, initialValue) {
  let accumulator = initialValue === undefined ? arr[0] : initialValue;
  for (let i = initialValue === undefined ? 1 : 0; i < arr.length; i++) {
    accumulator = callback(accumulator, arr[i], i, arr);
  }
  return accumulator;
}

В приведенном выше коде myReduceфункция принимает 3 параметра: массив для reduceобработки arr, функцию обратного вызова callbackи начальное значение аккумулятора initialValue. Если начальное значение не указано, в качестве начального значения аккумулятора используется первый элемент массива.

Далее в цикле, если есть initialValue, обратный вызов проходится от первого элемента. В это время второй параметр callabck начинается с первого элемента массива; если нет initialValue, он начинается со второго элемента Обход обратного вызова, в это время второй параметр обратного вызова начинается со второго элемента массива. Начиная со второго элемента массива, callback-функция выполняется для каждого элемента массива по очереди, а возвращаемое значение используется как следующая callback-функция Значение аккумулятора во время выполнения.

Наконец, функция myReducethe возвращает значение, возвращаемое последней функцией обратного вызова, которое является окончательным накопленным значением.

Эта простая reduceфункция не учитывает многих граничных случаев и сложных сценариев применения, но может помочь нам лучше понять reduceпринцип реализации функции.









Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .