可以在Javascript中使用reduce编写bigram(或ngram)函数
Possible to write bigram (or ngram) function using reduce in Javascript?
我知道Javascript中的.reduce
函数在其定义中具有"内置"previous
和current
变量的概念。所以我很好奇为什么这不起作用:
var bigrams = [0, 1, 2, 3, 4].reduce(function(previous, current) {
return [previous, current]
});
我不认为这意味着我认为它意味着什么,因为现在bigrams
包含:
[[[[0,1],2],3],4]
当我想要的是:
[[0,1],[1,2],[2,3],[3,4]]
我认为这与结果应该被推入累加器的事实有关(它可能应该是一个空数组,类似于:arr.reduce(/*magic*/, [])
?
- 我不应该使用
.reduce
来执行此操作吗? - 如果是这样,有没有另一种"功能性"方法可以做到这一点?
- 如何避免这种嵌套行为?
reduce的工作方式是将一个调用的输出用作下一个调用的输入。 如果我们将您的函数命名为 f
,您的调用等效于:
f(f(f(f(0, 1), 2), 3), 4)
换句话说,previous
并不意味着"原始数组中的上一项",而是表示"先前调用函数的结果"。
reduce
不是此任务的好选择,因为顾名思义,它旨在将数组减少到单个值。 执行此操作的一种"功能"方法是使用 zip
并用数组尾部(除第一个元素之外的所有元素)压缩数组,如这个 Haskell 示例所示。 但是,Javascript没有内置zip函数。 使用此答案中的第二个zip
实现:
function zip() {
var args = [].slice.call(arguments);
var shortest = args.length==0 ? [] : args.reduce(function(a,b){
return a.length<b.length ? a : b
});
return shortest.map(function(_,i){
return args.map(function(array){return array[i]})
});
}
你可以做:
var x = [0, 1, 2, 3, 4]
zip(x, x.slice(1))
但是,在 JavaScript 中,我认为大多数人可能只是迭代地这样做,就像在回答这个问题时一样。