我有一系列连续的时间戳。我需要抓住介于开始和结束时间之间的数组子集。简化示例如下所示:
timestamps = [ 5,7,12,13,15,23 ];
startTime = 6;
endTime = 18;
鉴于上面的例子,找到介于startTime
和endTime
之间的第一个和最后一个时间戳的索引的最有效方法是什么?
正确的脚本会发现并返回索引1& 4(timestamps[1], timestamps[4]
)
我可以遍历数组并进行比较,但是有更有效的方法吗?
(适用的CoffeeScript)
# Search ordered array for timestamps falling between 'start' & 'end'
getRangeBorderIndexes = (stack, start, end) ->
ar = []
ar[0] = getBorder( stack, start, "left" )
ar[1] = getBorder( stack, end, "right" )
return ar
# Use bisection (binary search) to find leftmost or rightmost border indexes
getBorder = (stack, value, side ) ->
mod1 = if side == "left" then 0 else -1
mod2 = if side == "left" then 1 else 0
startIndex = 0
stopIndex = stack.length - 1
middle = Math.floor( (stopIndex+startIndex)/2 )
while stack[middle] != value && startIndex < stopIndex
if value < stack[middle]
if value > stack[middle - 1] then return middle + mod1
stopIndex = middle - 1
else if value > stack[middle]
if value < stack[middle + 1] then return middle + mod2
startIndex = middle + 1
middle = Math.floor( (stopIndex+startIndex)/2 )
return if stack[middle] != value then -1 else middle
timestamps = [ 5,7,12,13,15,23 ]
startTime = 6
endTime = 18
getRangeBorderIndexes( timestamps, startTime, endTime) # returns [1,5]
@kennebec和@Shanimal给出了很好的回应,特别是如果你想要一个超级简单的方法来获取一个数组的子集。但是我需要子数组的索引而不是整个子数组。我做了一些测试,上面的例子一直需要大约7ms才能找到子数组的边界,即使在一个有1000万条目的数组上也是如此!
感谢@voithos指出我正确的方向。我还修改了this code以创建上面的解决方案。
答案 0 :(得分:2)
使用lodash / underscore库:
_.select(timestamps,function(i){
return i>=startTime && i<=endTime;
})
答案 1 :(得分:1)
循环很有效,但Array.filter更容易 -
var timestamps = [ 5,7,12,13,15,23 ],
startTime = 6,
endTime = 18;
var selected=timestamps.filter(function(itm){
return itm>=startTime && itm<=endTime;
});
/ *返回值:(数组) 7,12,13,15 * /
//过滤器内置于大多数浏览器中,但如果您需要在#9之前支持IE,则可以使用它:
if(!Array.prototype.filter){
Array.prototype.filter= function(fun, scope){
var T= this, A= [], i= 0, itm, L= T.length;
if(typeof fun== 'function'){
while(i<L){
if(i in T){
itm= T[i];
if(fun.call(scope, itm, i, T)) A[A.length]= itm;
}
++i;
}
}
return A;
}
}