【发布时间】:2017-03-07 18:49:14
【问题描述】:
给定一个数组,其元素是表单中的对象:
{
"description": "foo",
"startTime": 0,
"endTime": 100
}
我需要找到 startTime <= t <= endTime 的所有元素。
-
(endTime - startTime) >= 100,但时间差没有明确的上限,数组中每个对象的差也不一定相同。startTime可以为负数。 -
arr[i].startTime <= arr[i + 1].startTime,但对于endTime,不一定也是如此。 -
description不是唯一的,甚至不一定在给定的时间跨度内。 - 时间对应于视频中的毫秒数,很容易达到一小时或更长时间。如果 1 小时视频的整个长度有 100 毫秒持续时间的对象,则需要过滤 36,000 个数组元素。根据视频的不同,一个 100 毫秒的时间跨度可能很容易有十几个对象。
我目前的解决方案是一个简单的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
}
});
据我所知,filter 是作为线性搜索实现的。有没有更好的算法可以实现我的目标?也许是二分搜索的一些变体?
在我正在测试的 2 分钟演示视频/元数据中,大多数 filter 调用在大约 0.7 毫秒内完成。但是,其中一些需要 1-5 毫秒,我已经跟踪了一些极端异常值,例如 11 毫秒甚至 33 毫秒。我的“做事”循环通常在 0.1 毫秒内完成,重负载需要 4 毫秒,异常值需要 12 毫秒。最糟糕的是,getCurrentTime 函数是异步的,通常在调用它和调用回调之间需要 1-5 毫秒,负载在 50-60 毫秒左右,异常值超过 500 毫秒。考虑到此代码在传递给setInterval 的函数中,在播放视频时间隔运行(当前间隔为 250 毫秒,但最终我想我想使用 100 毫秒或更短的间隔),我当我开始使用时长超过一小时的视频时,我担心性能。
【问题讨论】:
-
比线性时间更快的唯一方法就是完全无事可做。
-
@peteb 也许你可以去
log(n),例如?这比线性 (n) 快。 -
@LuanNico 是的,但是他想要过滤的项目需要进行排序。如果它们没有以排序方式插入,那么你就有了这样的开销。
-
@peteb 它们按 startTime 排序。
-
@BrianS 这是一个关键的信息。集合的大小也是一个很好的信息。
标签: javascript arrays search