如何访问 .reduce() 传递的数组

How to access the array being passed by .reduce()

我有一个 JavaScript 对象:

const movies = [
  {'title' : 'Inception', 'rating' : 8.8},
  {'title' : 'Interstellar', 'rating' : 8.6},
  {'title' : 'The Dark Knight', 'rating' : 9.0},
  {'title' : 'Batman Begins', 'rating' : 8.3}
]

例如,我想做的是使用 .reduce() 计算平均评分,所以我被困在这里:

const averageRating = movies.filter(movie => movie['rating'] > 8.5).reduce((acc, movie) => (acc+movie['rating'])/2,  /* The rating of the first value of this array*/)

如何访问由 reduce() 处理的数组以获得第一部电影的评分(使用它的第一个 ELEMENT.rating 作为初始值)?我知道默认情况下分配给 acc 的第一个值是第一个,但在这种情况下它是一个对象。

我知道有更好的方法可以解决这个特殊情况,我已经实际解决了,但我不知道这样是否可以达到相同的结果?

const movies = [{
    'title': 'Inception',
    'rating': 8.8
  },
  {
    'title': 'Interstellar',
    'rating': 8.6
  },
  {
    'title': 'The Dark Knight',
    'rating': 9.0
  },
  {
    'title': 'Batman Begins',
    'rating': 8.3
  }
]
const averageRating = movies.filter(movie => movie['rating'] > 8.5).reduce((acc, movie) => (acc + movie['rating']) / 2,)

console.log(averageRating)

Array.reduce() 的第 4 个参数是传递给它的数组。

将累加器的初始值设置为 0 - 这将防止 reduce 在数组为空时抛出错误。将每个数字除以过滤后的数组长度,并将结果添加到累加器中以获得平均值。

const movies = [{"title":"Inception","imdbRating":8.8},{"title":"Interstellar","imdbRating":8.6},{"title":"The Dark Knight","imdbRating":9},{"title":"Batman Begins","imdbRating":8.3}]

const averageRating = movies
  .filter(movie => movie.imdbRating > 8.5)
  .reduce((acc, movie, i, arr) => acc + movie.imdbRating / arr.length, 0)
  
console.log(averageRating)

完整的 .reduce 签名是:

arr.reduce(callback( accumulator, currentValue, [, index[, array]] )[, initialValue])

基于此,你可以写:

const averageRating = movies
  .filter((movie) => movie["rating"] > 8.5)
  .reduce((acc, movie, index, array) => (acc + movie["rating"]) / array.length, 0);

并可以访问 reduce 函数中的 array

查询docs可以看到reduce的回调有如下签名

function(accumulator, currentValue, currentIndex, array)

因此

array
  .filter(x => ...)
  .reduce((ac, cv, i, ar) => {
    //here ar is the array you are calling reduce, ie the array resulting from filter
  })

如果您注意到 reduce 函数的 documentation,它接受四个参数。

  1. 累加器
  2. 当前值
  3. 当前索引
  4. 数组

因此,对于您的情况,您可以执行以下操作:

const averageRating = movies
                       .filter(movie => movie['rating'] > 8.5)
                       .reduce((acc, movie, idx, arr) => (acc+movie['rating'])/2)

啊好的,试试这个

const movies = [
  {'title' : 'Inception', 'rating' : 8.8},
  {'title' : 'Interstellar', 'rating' : 8.6},
  {'title' : 'The Dark Knight', 'rating' : 9.0},
  {'title' : 'Batman Begins', 'rating' : 8.3}
]

// On each reduce iteration you modifying object property,
// not array value. To calculate average, you adding acc.rating
// to current movie.rating and when current iteration equals
// array length (last iteration) you divide accumulated value
// by array length (number of entries that was accumulated).
const averageRating = movies.filter(movie => movie['rating'] > 8.5)
.reduce((acc, movie, i, a) => ({
  'rating': (acc.rating + movie.rating)/(i+1==a.length?a.length:1)
}));

console.log(averageRating);