我试图找到一个解决方案来找出数组中数字的出现次数,并遇到了以下解决方案:
const occurrences = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});
console.log(occurrences)
上面的代码按预期工作。但我无法正确理解它是如何工作的。有人可以简化并解释上面的 reduce 方法吗?提前致谢。
我认为棘手的部分只是:
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
注意这只是:
return (some_expression_with_side_effects), acc
...返回
acc
。有关详细信息,请查看 JavaScript 中的 comma operator。简而言之,表达式a, b
等于b
。使用它作为 reduce 的返回值只是确保累加器始终是同一个对象acc
。但是我们在减少时向该对象添加属性。
当我们减少数组中的项目时,副作用表达式执行以下操作:
请注意,我们实际上并没有使用
++acc[curr]
的返回值,我们只是依赖于它实际增加存储在 acc[curr]
的值的副作用。同样,我们不返回表达式 acc[curr] = 1
的值,而是依赖于它实际上将 acc[curr]
设置为初始值 1
的副作用。
reduce()
方法用于遍历数组,并根据一些逻辑从中累积单个值。
让我们分解代码:
const occurrences = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});
reduce()
方法有两个参数:
在array 的每个元素上执行的function。这个函数有两个参数:累加器(
acc
)和正在处理的当前值(curr
)。 accumulator 是在 function 的每次迭代中返回和累积的值。
累加器的可选初始值。在这种情况下,初始值是一个空对象{}
.让我们找出
函数作为第一个参数传递给reduce()
function (acc, curr) {
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}
在每次迭代中,此函数检查当前值 (curr
) 是否已作为键存在于累加器 (
acc
) 中。如果是,它会增加该key 的 value。如果不是,它将 key 添加到累加器,value 为 1. 分解逻辑:
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
acc[curr]
:这将检查当前的value(
curr
)是否作为累加器(
acc
)中的key存在。
? ++acc[curr]
:如果键存在,它会增加与该key关联的值。
: acc[curr] = 1
:如果key不存在,它将key添加到累加器,值为1.
, acc
:最后返回更新后的累加器
acc
对象中的新数字的计数初始化为 1。所有迭代完成后,将累加器对象的最终值赋值给 occurrences 变量并打印到控制台:
console.log(occurrences) // {2: 5, 4: 1, 5: 3, 9: 1}
这表明原数组中数字2出现了5次,数字5出现了3次,数字4出现了1次,数字9出现了1次