我确信这个功能很常见(或者可能是其他方式可以实现),但我不确定它的名称。我想的是一个特定尺寸的滑动窗口: -
let slidingMap = (arr,size, f) => {
r = []
arr.reduce((acc, n) => {
let b = acc.concat(n);
if(b.length > size) {
b.shift();
}
if(b.length == size) {
r.push(f(b))
}
return b;
},[])
return r;
}
所以slidingMap([1,2,3,4,5,6], 2, b => b)
你得到[ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ], [ 5, 6 ] ]
和slidingMap([1,2,3,4,5,6], 3, b => b)
你得到[ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ] ]
或计算差异: -
slidingMap([1,2,3,7,5,6],2, b => b.reduceRight((a, n) => a? a-n : n))
你会得到[1,1,4,-2,1]
或移动平均线: -
slidingMap([1,2,3,7,5,6],3, b => b.reduce((a, n) => a+n,0)/b.length)
你得到[ 2, 4, 5, 6 ]
那么,是否有通常实现的功能可以实现这一目标?
更新
Probablly更好地实施为
let sliding = (arr,size) => {
r = []
arr.reduce((acc, n) => {
let b = acc.concat(n);
if(b.length > size) {
b.shift();
}
if(b.length == size) {
r.push(b)
}
return b;
},[])
return r;
}
然后只使用地图
sliding([1,2,3,4,5],2).map(somefunc);
或者使用zip并跳过(在这种情况下使用lodash)
let sliding = (arr, size) =>
_.zip(..._.range(size).map(i => arr.slice(i)))
.filter(a => !a.some(v => v == undefined))
这里唯一的技巧是zip会在没有匹配时插入undefined,因此需要将其过滤掉。