javascript reduce

含义

reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。

语法

arr.reduce(callback[, initialValue])

参数

callback
执行数组中每个值的函数,包含四个参数:
accumulator
累加器累加回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(如下所示)。

currentValue
数组中正在处理的元素。
currentIndex 可选
数组中正在处理的当前元素的索引。 如果提供了initialValue,则索引号为0,否则为索引为1。
array 可选
调用reduce的数组
initialValue 可选
用作第一个调用 callback的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
Link to section
返回值
函数累计处理的结果

例子

求数组[1,2,3,4,5]里所有值的和

// 1 遍历求和
let count = 0
let arr = [1, 2, 3, 4, 5]
for (let i = 0; i < arr.length; i++) {
  count += arr[i]
}
console.log(count)
// output 15

// 2 eval
let count = eval([1, 2, 3, 4, 5].join('+'))
console.log(count)
// output 15

// 3 reduce
let count = [1, 2, 3, 4, 5].reduce((a, b) => a + b)
console.log(count)
// output 15

将二维数组转化为一维

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
 ( acc, cur ) => acc.concat(cur),
 []
);

计算数组中每个元素出现的次数

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

var countedNames = names.reduce(function (allNames, name) { 
  if (name in allNames) {
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

使用扩展运算符和initialValue绑定包含在对象数组中的数组

// friends - an array of objects 
// where object field "books" - list of favorite books 
var friends = [{
  name: 'Anna',
  books: ['Bible', 'Harry Potter'],
  age: 21
}, {
  name: 'Bob',
  books: ['War and peace', 'Romeo and Juliet'],
  age: 26
}, {
  name: 'Alice',
  books: ['The Lord of the Rings', 'The Shining'],
  age: 18
}];

// allbooks - list which will contain all friends' books +  
// additional list contained in initialValue
var allbooks = friends.reduce(function(prev, curr) {
  return [...prev, ...curr.books];
}, ['Alphabet']);

// allbooks = [
//   'Alphabet', 'Bible', 'Harry Potter', 'War and peace', 
//   'Romeo and Juliet', 'The Lord of the Rings',
//   'The Shining'
// ]

数组去重

let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
let result = arr.sort().reduce((init, current) => {
  if (init.length === 0 || init[init.length - 1] !== current) {
    init.push(current);
  }
  return init;
}, []);
console.log(result); //[1,2,3,4,5]

数组取最大值和最小值

let data = [1,4,2,2,4,5,6,7,8,8,9,10]
//取最小值
let min = data.reduce((x, y) => x > y ? y : x)
//取最大值
let max = data.reduce((x, y) => x > y ? x : y)

ES5的实现

if (!Array.prototype.reduce) {
  Object.defineProperty(Array.prototype, 'reduce', {
    value: function(callback /*, initialValue*/) {
      if (this === null) {
        throw new TypeError( 'Array.prototype.reduce ' + 
          'called on null or undefined' );
      }
      if (typeof callback !== 'function') {
        throw new TypeError( callback +
          ' is not a function');
      }

      // 1. Let O be ? ToObject(this value).
      var o = Object(this);

      // 2. Let len be ? ToLength(? Get(O, "length")).
      var len = o.length >>> 0; 
      // 😂 >>表示是带符号的右移:按照二进制把数字右移指定数位,高位如符号位为正补零,符号位负补一,低位直接移除
      // 😂 >>>表示无符号的右移:按照二进制把数字右移指定数位,高位直接补零,低位移除。

      // Steps 3, 4, 5, 6, 7      
      var k = 0; 
      var value;

      if (arguments.length >= 2) {
        value = arguments[1];
      } else {
        while (k < len && !(k in o)) {
          k++; 
        }

        // 3. 长度为0 且初始值不存在 抛出异常
        if (k >= len) {
          throw new TypeError( 'Reduce of empty array ' +
            'with no initial value' );
        }
        value = o[k++];
      }

      // 8. Repeat, while k < len
      while (k < len) {
        // a. Let Pk be ! ToString(k).
        // b. Let kPresent be ? HasProperty(O, Pk).
        // c. If kPresent is true, then
        //    i.  Let kValue be ? Get(O, Pk).
        //    ii. Let accumulator be ? Call(
        //          callbackfn, undefined,
        //          « accumulator, kValue, k, O »).
        if (k in o) {
          value = callback(value, o[k], k, o);
        }

        // d. Increase k by 1.      
        k++;
      }

      // 9. Return accumulator.
      return value;
    }
  });
}
posted @ 2019-03-02 18:26  邱秋  阅读(155)  评论(1编辑  收藏  举报