问题描述
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)
解决方法
如果您注意到 reduce
函数的 documentation,它接受四个参数。
- 累加器
- 当前值
- 当前索引
- 数组
因此,在您的情况下,您可以执行以下操作:
const averageRating = movies
.filter(movie => movie['rating'] > 8.5)
.reduce((acc,movie,idx,arr) => (acc+movie['rating'])/2)
,
Array.reduce()
的第四个参数是传递给它的数组。
将累加器的初始值设置为 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,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,index,array) => (acc + movie["rating"]) / array.length,0);
并且可以访问reduce函数内的array
查询docs可以看到reduce
的回调有如下签名
function(accumulator,currentIndex,array)
因此
array
.filter(x => ...)
.reduce((ac,cv,ar) => {
//here ar is the array you are calling reduce,ie the array resulting from filter
})
,
好的,试试这个
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,a) => ({
'rating': (acc.rating + movie.rating)/(i+1==a.length?a.length:1)
}));
console.log(averageRating);