给定一个数组,其元素是以下形式的对象:
{
"description": "foo",
"startTime": 0,
"endTime": 100
}
我需要找到startTime <= t <= endTime
。
(endTime - startTime) >= 100
,但时间差没有明确的上限,数组中每个对象的差异也不一定相同。 startTime
可能是否定的。arr[i].startTime <= arr[i + 1].startTime
,但<{1}}的 必须如此。endTime
不唯一,甚至在给定的时间范围内也不一定。我目前的解决方案是一个简单的description
电话:
Array.prototype.filter
据我所知,video.getCurrentTime((s) => { // library function; s=current time in seconds of the video
const ms = Math.floor(s * 1000);
const itemsAtTime = metadata.filter((o) => { // metadata is array of objects
const start = o.startTime;
const end = o.endTime;
return start <= ms && ms <= end;
});
// ...
for (let obj of itemsAtTime) {
// do stuff
}
});
是作为线性搜索实现的。有没有更好的算法可以实现我的目标?也许是二元搜索的一些变体?
在我测试的2分钟演示视频/元数据中,大多数filter
调用在大约0.7毫秒内完成。但是,其中一些需要1-5毫秒,而且我已经跟踪了一些极端异常值,如11毫秒甚至33毫秒。我的&#34;做东西&#34;循环通常在0.1ms内完成,重负载需要4ms,异常值在12ms。最糟糕的是,filter
函数是异步的,通常在调用它和调用回调之间花费1-5ms,在50-60ms附近有大量负载,而异常值高达500ms。考虑到这个代码是在传递给getCurrentTime
的函数中,在播放视频时间隔正在运行(目前间隔为250毫秒,但最终我认为我想使用100毫秒或更短的间隔) ,当我开始使用一小时以上的持续时间视频时,我很担心表现。
答案 0 :(得分:1)
您可以进行二元搜索,找到startTime <= ms
的第一个项目。然后,您可以从该索引开始线性过滤。这是我能想到的最好的。
所以,比如:
const binaryWhereMin = function(arr, ms) {
// write your function that returns the index of first element start <= ms
};
let index = binaryWhereMin(arr, ms);
let result = arr.splice(index, arr.length).filter(/* your filter */);
我看不到更好的方法,因为结尾没有排序。
这里有一个binary search example。但你需要改变它而不是搜索一个特定的元素(它不会那么高效!但我相信它仍然比你的更好)。