До сих пор мы делали некоторые чистые служебные функции (например, карту, фильтр).
Сегодня мы сделаем три функции: «уменьшить» и «карри». Они будут хорошими инструментами на следующем этапе - конвейерной обработке.
1. Уменьшить
Функция Reduce принимает коллекцию, итерацию и аккумулятор (необязательно, начальное значение). И он возвращает только один накопленный результат выполнения каждого элемента с collection
по iteratee
.
Аккумулятор, это 3-й параметр, необязательное значение. Если нет, первый элемент коллекции будет начальным значением.
Итеративным называется каждый элемент коллекции. Он берет результат предыдущего итератора и текущий элемент и возвращает новый результат.
const usersMock = [ { id: 1, name: 'user1', age: 11 }, { id: 2, name: 'user2', age: 21 }, { id: 3, name: 'user3', age: 23 }, { id: 4, name: 'user4', age: 11 }, { id: 5, name: 'user5', age: 37 }, { id: 6, name: 'user6', age: 23 }, ]; test('reduce', () => { expect(reduce(usersMock, (sum, user) => sum + user.age, 0)).toBe(126); });
В этом коде reduce возвращает сумму возраста пользователей. Функция iteratee получает начальное значение 0 и добавляет возраст первого пользователя. Если первый цикл завершен, второй цикл начинается с первого результата и второго элемента. Повторяйте этот процесс до конца. Тогда как мы можем реализовать «сокращение»? Он также просматривает коллекцию, поэтому давайте воспользуемся "each".
const each = require('../each'); function reduce(collection, iteratee, accumulator) { let iterable = collection; let result = accumulator; if (arguments.length == 2) { result = collection[0]; iterable = Array.prototype.slice.call(collection, 1); } each(iterable, (value) => { result = iteratee(result, value); }); return result; } module.exports = reduce;
Берем 2 или 3 аргумента. Если их 2, мы используем первый элемент в качестве третьего аргумента. И, пройдя цикл «each», установите результат равным возвращаемому значению итерации.
Карта, Фильтр, Уменьшение
Вся большая часть обработки данных состоит из этих трех функций: сопоставления, фильтрации и сокращения.
«Карта» однозначно сопоставляет данные. Он изменяет каждое значение данных, поэтому возвращает коллекцию той же длины.
«Фильтр» фильтрует данные в соответствии с условиями. Нет никаких изменений в каждом значении. Но длину данных можно изменить.
Наконец, «уменьшить» возвращает только одно значение. Он объединяет все элементы, чтобы создать один результат.
2. Карри, карри-право
Карри - очень интересная функция. Он принимает функцию и возвращает новую функцию. Любопытно, что он заставляет функцию ввода принимать ввод последовательно!
Давайте сначала посмотрим на код.
function curry(fn) { return (first, ...args) => args.length ? fn(first, ...args) : (...args2) => fn(first, ...args2); } module.exports = curry;
«Карри» возвращает новую функцию. Если новая функция принимает только один входной параметр, она возвращает функцию с первым набором входных данных. Так что мы можем использовать его, когда нам это нужно. Как мы можем это использовать? Подумайте об этом коде.
test('curry', () => { const curryReduce = curry(reduce); const numbersReduce = curryReduce([1, 2, 3, 4, 5]); const sumTotal = numbersReduce((sum, value) => sum + value, 0 ); const sumOdds = numbersReduce((sum, value) => value % 2 ? sum + value : sum, 0 ); expect(sumTotal).toBe(15); expect(sumOdds).toBe(9); });
Мы назвали «карри», указав на входе «уменьшить». «Reduce» принимает только 2 или 3 аргумента, но curryReduce теперь может принимать только первый аргумент. В результате была создана функция numbersReduce. можем поставить любой итератор и аккумулятор!
Мы также можем сделать функцию «каррир». Это заставляет функцию ввода сначала принимать только второй аргумент.
function curryr(fn) { return (first, ...args) => args.length ? fn(first, ...args) : (innerFirst, ...args2) => fn(innerFirst, first, ...args2); } module.exports = curryr;
Таким образом, в случае «сокращения» мы можем поставить на первое место итеративную логику.
test('curryr', () => { const curryrReduce = curryr(reduce); const sumReduce = curryrReduce((sum, value) => sum + value); const sumTotal = sumReduce([1, 2, 3, 4, 5]); expect(sumTotal).toBe(15); });
Как вы увидите из будущего, мы обычно сначала ставим логику итеративного элемента, а затем вводим данные таким же образом.
Теперь, когда все ингредиенты готовы, давайте в следующий раз приступим к конвейерной обработке с использованием функций!