我对js很新,尝试用reduce替换for循环并遇到麻烦。
据我了解,||
仅评估左操作数。如果它真实,它就作为价值传递。如果它是假的,那么右操作数在没有被评估的情况下被传递,因为它是决定因素。
出于某种原因,这适用于for循环,但不适用于reduce。难道不能在第一次迭代时阅读obj[val]
或obj[arr[ind]]
使其返回0 + 1
吗?
'use strict';
let strings = ["One", "Two", "Two", "Three", "Three", "Three"];
let findMostCommon = (arr) => {
let str;
let obj;
let keys;
let counter;
str = "";
obj = {};
counter = 0;
for (let i = 0; i < arr.length; i++){
console.log(arr[i]); // One, Two, Two, Three, etc.
obj[arr[i]] = (obj[arr[i]] || 0) + 1; // Works
}
/*
arr.reduce((obj, val, ind, arr) => {
obj[val] = (obj[val] || 0) + 1;
}, obj)
obj[val] = (obj[val] || 0) + 1;
^
TypeError: Cannot read property 'Two' of undefined
*/
/*
arr.reduce((obj, val, ind, arr) => {
obj[arr[ind]] = (obj[arr[ind]] || 0) + 1;
}, obj)
obj[arr[ind]] = (obj[arr[ind]] || 0) + 1;
^
TypeError: Cannot read property 'Two' of undefined
*/
keys = Object.keys(obj);
for (let i in obj){
if (obj[i] > counter){
counter = obj[i]
}
}
str = keys[counter - 1];
return str;
}
console.log(
findMostCommon(strings)
)
答案 0 :(得分:2)
在reduce
中,您之前获得的值是您在上一次迭代中返回的值。所以:
[1,2,3,4,5,6].reduce(function(sumSoFar, currentNumber){
return sumSoFar + currentNumber; // whatever I return here is the next value
}, 0);
在这里使用reduce的正确方法是将属性添加到对象并将其返回。
arr.reduce((obj, val, ind, arr) => {
obj[arr[ind]] = (obj[arr[ind]] || 0) + 1; // arr[ind] is just val btw
return obj; // LOOK AT ME
}, obj);
当然,使用较新的ES功能可以获得更好的效果:
arr.reduce((obj, val) => {
return {...obj, [val] : (obj[val] || 0) + 1 }
}, {});
请注意,后一版本(或者如果您受ES2015限制,使用Object.assign)将在每个回合中创建一个新对象。对于可能存在问题的数千个对象。
使用lodash,顺便说一下,这只是_.countBy(arr)
:)