В ES5 новый метод массива Reduce (). Мне интересно, если кто-то может объяснить более подробно.

var test = [1, 2, 3, 4, 5].reduce(function(inital, item, idx) {
  return inital + item
}, 0);

console.log(test);

В этом примере мы точно знаем, что начальный аргумент равен 0 и проходит через функцию обратного вызова. Может ли кто-нибудь объяснить мне сферу действия первоначального аргумента?

Если предположить, что [1, 2, 3, 4, 5] - это то, что возвращается из воображаемого метода, и вы хотите вернуть форму объекта, ключом которого является idx, а значением является Math.pow (idx, 2). {1: 1, 2: 4, 3: 9, 4:16, 5:25}. Может кто-нибудь, пожалуйста, объясните мне это?

ТАКЖЕ :) у нас есть массив с буквами. некоторые повторяют некоторые нет. Я хочу посчитать, сколько букв в массиве и превратить его в объектную форму. {a: 5, .... z: 7}; Кто-нибудь, пожалуйста, проведите меня с этим. Я хорошо понимаю forEach и map, но с помощью метода Reduce мне очень трудно разобраться с этим.

Заранее спасибо

2
DevBear15 16 Дек 2015 в 06:04

3 ответа

Лучший ответ

Представьте, что у нас есть следующий фрагмент кода где-то в нашем приложении:

function addLog() {
  console.log(arguments)
  return arguments[0] + arguments[1]
}

console.log([2,3,4].reduce(addLog))
console.log([2,3,4].reduce(addLog, 1))

К сожалению, у нас есть зависимость от библиотеки badlibrary.js, которая перезапишет ES5 по умолчанию Array.prototype.reduce:

Badlibrary.js :

Array.prototype.reduce = Infinity

Поскольку эта библиотека является зависимостью для нашего приложения, мы не можем удалить библиотеку. Единственное решение - это исправить Array.prototype.reduce, переписав его перед тем, как запустить наш код.

Оказывается, это не так сложно. Мы можем просто прочитать документацию Mozilla по сокращению и перевести английский на JavaScript.

Array.prototype.reduce = function(callback, initialValue) {
  var resultSoFar, i
  var n = this.length
  if (typeof initialValue !== 'undefined') {
    resultSoFar = initialValue
    i = 0
  } else {
    resultSoFar = this[0]
    i = 1
  }
  for (; i < n; i++) {
    resultSoFar = callback(resultSoFar, this[i], i, this)
  }
  return resultSoFar
}

Наш код теперь работает, даже с этой пользовательской версией reduce, и теперь reduce больше не является "черным ящиком". Мы могли бы легко написать это сами, если бы захотели, и на самом деле это то, что делали несколько человек до стандартизации ES5. Кстати, некоторые люди по-прежнему используют браузеры, которые поддерживают только до ES3. Чтобы reduce был по-настоящему совместим с различными браузерами, нам все еще нужно отрегулировать его или использовать служебную библиотеку, такую как Underscore / Lodash / Ramda. Использование служебной библиотеки IMO - лучшее и простое решение.

ТАКЖЕ :) у нас есть массив с буквами. некоторые повторяют некоторые нет. Я хочу посчитать, сколько букв в массиве и превратить его в объектную форму. {a: 5, .... z: 7}; Кто-нибудь, пожалуйста, проведите меня с этим. Я хорошо понимаю forEach и map, но с помощью метода Reduce мне очень трудно разобраться с этим.

Мы хотим вернуть объект JS с буквами в качестве ключей и их количеством в качестве значений. Мы вызвали это значение resultSoFar в нашей функции reduce, и мы собираемся создать это значение, вызвав нашу функцию для каждого из элементов массива. Наше начальное значение должно быть пустым объектом. В нашей функции мы возьмем текущее письмо и попытаемся добавить 1 к его количеству. Если это приводит к NaN (что произойдет, если счет не определен, т.е. когда мы видим букву в первый раз и счет еще не назначен), тогда мы должны присвоить значение 1 вместо этого, так как его новый Письмо считать, и мы видим один из них.

Имея в виду эту теорию, код счета может быть записан следующим образом:

var letters = ['a', 'b', 'c', 'a', 'b', 'a']
console.log(letters.reduce(function(counts, currentLetter) {
    var currentLetterCount = counts[currentLetter]
    counts[currentLetter] = currentLetterCount + 1 || 1
    return counts
  }, {}))
1
Shashank 16 Дек 2015 в 04:33

Метод redu () - это итератор, он перебирает все элементы в массиве и что-то делает с результатами. Функция Reduce () принимает функцию обратного вызова. Эта функция на самом деле выполняет все, что вы хотите, для каждой итерации. Эта функция является специальной функцией

Первый параметр, который принимает эта функция: предыдущее значение второй параметр, который принимает эта функция - это текущее значение и два других параметра (пусть это будет просто)

Давайте рассмотрим, у нас есть массив

arr=[1,2,3,4,5,6]

Используя уменьшение путем создания функции под названием сумма

function sum(previousvalue,currentvalue,index,ar){
return previousvalue+currentvalue
}

И, наконец, мы помещаем ссылку на эту функцию в методе Reduce.

arr.reduce(sum)

Выполняя это, мы получаем 21

Что на самом деле делает эта специальная функция? Давайте рассмотрим

[ 1,2,3,4,5,6 ]

Функция сумма говорит

Wrong! "let me take the current element value in this array " == 1


Right! # the function starts at the second element in the array so the previous element is the 1st element

 "let me add the current element value to the prev. element value in this array and remember this value " == 1+2


"okay I am moving on to the next value"==3

"okay..I will add the next value to the previous summed up value"==3+3
"now I will save this value and do the same thing again until I loop to the end"

Но подождите, что практического использования это, я могу написать это легко, не используя функцию Reduce?

Это похоже на функцию генератора (как в некоторых языках, таких как python) .. она не запоминает значения, кроме предыдущего значения вызова и текущего значения ... (некоторое преимущество в эффективности памяти)

< Сильный > пример поиск скользящих средних

   function sum(previousvalue,currentvalue,index,ar){
    return (previousvalue+currentvalue/2)
    }

Вышеприведенная функция является ревизией того же старого функционала, который я использовал

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

0
repzero 16 Дек 2015 в 06:09

Метод, который вы передаете в .reduce, принимает параметры previous_returned_value, current_iteration_item, current_iteration_index, context_array

Это означает, что каждый раз, когда он вызывается, первым аргументом является значение return из предыдущего вызова

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

Вы можете прочитать документы MDN об этом здесь


вернуть форму объекта, ключом которого является idx, а значением - Math.pow (idx, 2)

  • Вы передаете исходный пустой объект
  • Ваш метод добавляет свойства к этому объекту
  • Метод возвращает объект

Например

 [1, 2, 3, 4, 5].reduce((o, e) => (o[e] = Math.pow(e, 2), o), {});
 // Object {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

посчитать, сколько букв в массиве и превратить его в объект

  • Снова перейдите в исходный пустой объект
  • Метод устанавливает / добавляет 1 к объекту на основе текущей буквы
  • Метод возвращает объект

Так опять

['f', 'o', 'o', 'b', 'a', 'r'].reduce((o, e) => (o[e] = (o[e] || 0) + 1, o), {});
// Object {f: 1, o: 2, b: 1, a: 1, r: 1}

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

function (o, e) {
    o[e] = Math.pow(e, 2);
    return o;
}
// same as
function (o, e) {
    return o[e] = Math.pow(e, 2), o;
}
// similar to
(o, e) => {
    return o[e] = Math.pow(e, 2), o;
}
// same as
(o, e) => (o[e] = Math.pow(e, 2), o);
4
Paul S. 16 Дек 2015 в 03:18