Вы можете увидеть часть 1 здесь: https://medium.com/@ericholiveira/implementing-reduce-in-javascript-part-1-7ea8711e194

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

На этой неделе мы узнаем, как реализовать функции map, filter и flatMap, используя только функцию reduce, и в качестве бонуса мы увидим, как с его помощью можно сериализовать выполнение обещаний.

Реализация функции - лучший способ научиться ее использовать, поэтому давайте перейдем к реализации :)

Карта

Наша функция map получает два параметра: массив и функцию. Результатом этого является новый массив, содержащий результат выполнения данной функции для каждого элемента данного массива.

Реализация его с использованием только функции reduce:

const map = function(iterable,fn){
  return reduce(iterable,(acc,n)=>acc.concat([fn(n)]),[])
}
console.log(map([1,2,3],i=>i+1)) //Prints [2,3,4]

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

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

Функция, переданная в качестве второго параметра функции reduce, действительно проста, она просто накапливает в новом массиве результат функции сопоставления (в нашем примере i = ›i + 1) для каждого элемента данного массива.

Фильтр

Функция filter также получает два параметра, массив и функцию условия. Результатом этого является новый массив, содержащий только элементы, удовлетворяющие заданному условию.

const filter = function(iterable,fn){
  return reduce(iterable,(acc,n)=>fn(n)?acc.concat([n]):acc,[])
}
console.log(filter([1,2,3,4],i=>i<3)) // Prints [1,2]

Как видите, реализация аналогична той, что используется на карте, но теперь функция, переданная в сокращение, проверяет, удовлетворяет ли текущий элемент заданному условию, и, если оно истинно, помещает его в результат.

FlatMap

Посмотрите на следующий код:

console.log(map([1,2],i=>[i,i+1])) //Prints [[1,2],[2,3]]

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

Проще говоря, flatMap в основном выполняет сопоставление, а затем выравнивает результат.

Реализация также очень проста:

const flatMap = function(iterable,fn){
  return reduce(iterable,(acc,n)=>acc.concat(fn(n)),[])
}
console.log(flatMap([1,2],i=>[i,i+1]))//Prints [1,2,2,3]

Реализация аналогична map, единственное изменение заключается в том, что мы выполняем concat (fn (n)) вместо concat ([fn (n)]) (на карте function), потому что в первом случае, если результатом fn (n) является массив, он будет объединяться с массивом аккумуляторов, сохраняя плоскую структуру.

Обещания

Для последнего еще одно действительно интересное использование reduce - использовать его для выполнения одного за другим обещаний и накопления результата.

const sumPromises = function(promiseFunctions){
  return reduce(promiseFunctions,async (accPromise,next)=>{
    const accumulator = await accPromise
    const currentResult = await next()
    return accumulator + currentResult
  },Promise.resolve(0))
}
const promiseFunctions = [
  ()=> Promise.resolve(1),
  ()=> Promise.resolve(2),
  ()=> Promise.resolve(3)
]

sumPromises(promiseFunctions).then(console.log)// Prints 6

Не торопитесь, посмотрите на приведенный выше код.

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

Вот и все, хлопайте, если вам понравилось, и не забудьте подписаться на меня здесь и в твиттере https://twitter.com/Oliveira_Erich