Array.prototype.reduce()

reduce() 方法按顺序在数组的每个元素上执行用户提供的“reducer”回调函数,并传入对前一个元素进行计算的返回值。 在数组的所有元素上运行 reducer 的最终结果是单个值。


使用 reduce 方法分析数据

reduce()(即Array.prototype.reduce()),是 JavaScript 所有数组操作中最常用的方法。

几乎可以用 reduce 方法解决所有数组处理问题。

reduce 方法是处理数组更通用的方式,而且 filter 和 map 方法都可以当作是 reduce 的特殊实现。

reduce 方法遍历数组中的每个项目并返回单个值(即字符串、数字、对象、数组)。 这是通过在每次迭代中调用一个回调函数来实现的。

回调函数接受四个参数。

  • 第一个参数称为叠加器,它是上一次迭代中回调函数的返回值

  • 第二个参数是当前正在处理的数组元素

  • 第三个参数是该参数的索引

  • 第四个参数是在其上调用 reduce 方法的数组。

除了回调函数,reduce 还有一个额外的参数做为叠加器的初始值。
如果没有第二个参数,会跳过第一次迭代,第二次迭代给叠加器传入数组的第一个元素。

示例1:

给 users 数组使用 reduce 方法,返回所有用户数组的和。 为了简化,例子仅使用了回调函数的第一个参数和第二个参数。

1
2
3
4
5
6
7
8
9

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const sumOfAges = users.reduce((sum, user) => sum + user.age, 0);
console.log(sumOfAges); // 64

示例2:

返回一个包含用户名称做为属性,其年龄做为值的对象。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const usersObj = users.reduce((obj, user) => {
  obj[user.name] = user.age;
  return obj;
}, {});
console.log(usersObj); // { John: 34, Amy: 20, camperCat: 10 }

更复杂的例子:

watchList 是包含一些电影信息的对象。
使用 reduce 查找由 Christopher Nolan 导演的电影的 IMDB 评级平均值。
回想一下之前的例子,如何 filter 数据,以及使用 map 来获取你想要的数据。
可能需要创建其他变量,并从 getRating 函数返回平均评分。
请注意,评级在对象中是字符串,需要将其转换为数字再用于数学运算。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

// 全局变量
const watchList = [
  {
    "Title": "Inception",
    "Year": "2010",
    "Director": "Christopher Nolan",
    "imdbRating": "8.8"
  },
  {
    "Title": "Interstellar",
    "Year": "2014",
    "Director": "Christopher Nolan",
    "imdbRating": "9.0"
  }
];

function getRating(watchList) {

  let averageRating = watchList
    // 使用过滤器查找克里斯托弗·诺兰 (Christopher Nolan) 导演的电影
    .filter(film => film.Director === "Christopher Nolan")
    // 使用 map 将他们的评分从字符串转换为数字
    .map(film => Number(film.imdbRating))
    // 使用 reduce 将他们的评分加在一起
    .reduce((sumOfRatings, rating) => sumOfRatings + rating) /
    // 除以诺兰片数得到平均评分
    watchList.filter(film => film.Director === "Christopher Nolan").length;

  return averageRating;
}

console.log(getRating(watchList)); // 8.9

使用高阶函数 map、filter 或者 reduce 来解决复杂问题

已经接触了高阶函数如 map()、 filter() 和 reduce()的使用,是时候用它们来完成一些复杂的挑战了。

使用 map()、filter() 和 reduce() 的任何组合完成 squareList 函数的代码。

传递一个包含实数的数组给函数时,函数应返回一个新的数组,只包含正整数(小数不是整数)的平方值, 例如 [-3, 4.8, 5, 3, -3.2] 这样一个包含实数的数组。

注意: 函数不应该包含任何形式的 for 或者 while 循环或者 forEach() 函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

const squareList = arr => {

  // return arr
  //   .filter(num => num > 0 && num % parseInt(num) === 0)
  //   .map(num => Math.pow(num, 2));
  
  // 或者
  return arr.reduce((sqrIntegers, num) => {
    return Number.isInteger(num) && num > 0
      ? sqrIntegers.concat(num * num)
      : sqrIntegers;
  }, []);

};

const squaredIntegers = squareList([-3, 4.8, 5, 3, -3.2]);
console.log(squaredIntegers); // [ 25, 9 ]