Подробное объяснение метода уменьшения массива JS

JavaScript

Обзор

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

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

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

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

  • Аккумулятор: MDN интерпретируется как аккумулятор, но я не думаю, что это целесообразно.По моему мнению, он должен быть до текущего элемента, а все предыдущие элементы массива обрабатываются функцией редьюсера.Накопленный результат
  • Текущий: текущий исполняемый элемент массива.
  • CurrentIndex: индекс элемента массива, выполняемого в данный момент.
  • SourceArray: исходный массив, то есть массив, вызывающий метод сокращения.

Если передан второй параметр, метод сокращения начнет накопительное выполнение на основе этого параметра.

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

Вот наиболее понятный пример: суммирование массивов

    const arr = [1, 2, 3, 4]
    const accumulator = (total, current, currentIndex, arr) => {
      console.log(total, current, currentIndex, arr);
      return total + current
    }
    console.log(arr.reduce(accumulator))

Результат выполнения следующий:

img

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

Всего было выполнено три исполнения для получения окончательного результата. Если передается начальное значение, каков порядок выполнения?

console.log(arr.reduce(accumulator, 3))

Результат выглядит следующим образом:

img

На этот раз переданное начальное значение используется как начальная точка накопления, а затем редьюсер по очереди выполняется над элементами массива.

Предполагая, что метод сокращения вызывается для пустого массива без начального значения, будет сообщено об ошибке:

Uncaught TypeError: Reduce of empty array with no initial value

некоторое использование

Я рассказал о некоторых концепциях, но сценарии использования более важны.Давайте посмотрим на использование метода сокращения.

составить функцию

Compose – это форма функционального программирования. Он используется для объединения нескольких функций. Возвращаемое значение предыдущей функции используется в качестве входного параметра текущей функции, а возвращаемое значение текущей функции используется в качестве входного параметра следующей функции. следующая функция Эффект несколько похож на модель Onion для промежуточного программного обеспечения koa.

[a, b, c, d] => a(b(c(d())))

По сути, он аналогичен накоплению, за исключением того, что операция накопления становится входным параметром выполнения, а результат сложения становится возвращаемым значением выполнения. Compose используется в applyMiddleware Redux, чтобы гарантировать, что окончательная отправка будет результатом, обработанным всем промежуточным программным обеспечением.

Давайте в качестве примера возьмем compose в applyMiddleware, сначала посмотрим на использование:

const result = compose(a, b, c)(params)

Реализация такая:

(params) => a(b(c(params)))

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

Взгляните на реализацию:

function compose(...funcs) {
  // funcs是compose要组合的那些函数,arg是componse返回的函数的参数
  if (funcs.length === 0) {
    // 如果没有传入函数,那么直接返回一个函数,函数的返回值就是传进来的参数
    return arg => arg
  }
  if (funcs.length === 1) {
    // 如果只传入了一个函数,直接返回这个函数
    return funcs[0]
  }

  return funcs.reduce((all, current) => {
    return (...args) => {
      return all(current(...args))
    }
  })
}

сглаженный массив

const array = [[0, 1], [2, 3], [4, 5]]
const flatten = arr => {
  return arr.reduce((a, b) => {
    return a.concat(b)
  }, [])
}
console.log(flatten(array)); // [0, 1, 2, 3, 4, 5]

Давайте посмотрим на процесс выполнения,

  • Первое выполнение, начальное значение передается в[], перейдите к обратному вызову сокращения, параметр a это[], параметр b является первым элементом массива[0, 1], внутри обратного вызова[].cancat([0, 1])
  • Второе выполнение, параметр обратного вызова a для сокращения является результатом последнего выполнения обратного вызова.[0, 1], на этот раз продолжайте использовать его для объединения второго элемента массива[2, 3], получил ответ[0, 1, 2, 3]Продолжить выполнение в качестве параметра следующего выполнения обратного вызова
  • ...и так далее

Что делать, если массив такой?[[0, [111, 222], 1], [2, [333, [444, 555]], 3], [4, 5]], на самом деле добавить рекурсивный вызов можно

const array = [[0, [111, 222], 1], [2, [333, [444, 555]], 3], [4, 5]]

const flatten = arr => {
  return arr.reduce((a, b) => {
    if (b instanceof Array) {
      return a.concat(flatten(b))
    }
    return a.concat(b)
  }, [])
}
console.log(flatten(array)); // [0, 111, 222, 1, 2, 333, 444, 555, 3, 4, 5]

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

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

const str = 'adefrfdnnfhdueassjfkdiskcddfjds'
const arr = str.split('')
const strObj = arr.reduce((all, current) => {
  if (current in all) {
    all[current]++
  } else {
    all[current] = 1
  }
  return all
}, {})

console.log(strObj) // {"a":2,"d":7,"e":2,"f":5,"r":1,"n":2,"h":1,"u":1,"s":4,"j":2,"k":2,"i":1,"c":1}

Дедупликация массива

const arr = ['1', 'a', 'c', 'd', 'a', 'c', '1']
const afterUnique = arr.reduce((all, current) => {
  if (!all.includes(current)) {
    all.push(current)
  }
  return all
}, [])
console.log(afterUnique); //  ["1", "a", "c", "d"]

звонить обещаниям по порядку

Этот метод фактически обрабатывает значение обещания и рассматривает значение предыдущего обещания как значение следующего обещания.

const prom1 = a => {
  return new Promise((resolve => {
    resolve(a)
  }))
}
const prom2 = a => {
  return new Promise((resolve => {
    resolve(a * 2)
  }))
}
const prom3 = a => {
  return new Promise((resolve => {
    resolve(a * 3)
  }))
}

const arr = [prom1, prom2, prom3]
const result = arr.reduce((all, current) => {
  return all.then(current)
}, Promise.resolve(10))

result.then(res => {
  console.log(res);
})

выполнить

Благодаря приведенному выше использованию характеристики сокращения можно обобщить:

  • Получите два параметра, первый — функция, функция получит четыре параметра: Accumulator Current CurrentIndex SourceArray, второй параметр — начальное значение.
  • Возвращаемое значение является кумулятивным результатом выполнения всех Аккумуляторов.
  Array.prototype.myReduce = function(fn, base) {
    if (this.length === 0 && !base) {
      throw new Error('Reduce of empty array with no initial value')
    }
    for (let i = 0; i < this.length; i++) {
      if (!base) {
        base = fn(this[i], this[i + 1], i, this)
        i++
      } else {
        base = fn(base, this[i], i, this)
      }
    }
    return base
  }

Для более технических статей вы можете обратить внимание на паблик аккаунт: один интерфейс

img