在某个时间点,我需要找到所有具有早于及晚于该时间点的目标。
目前我正在做以下事情:
for current_time = sorted_set_of_times;
target_set = find([Targets.First_Time] <= current_time ...
& [Targets.Last_Time] >= current_time);
% Using target_set here. Targets are not modified within this loop
end
MATLAB探测器告诉我这条线需要大约40分钟,有40,000个电话。
有没有办法可以更有效地做到这一点?
current_time
按顺序在for_loop中递增。我当时认为这种情况总是在增加,这可以用来简化一些测试。例如,Targets.First_Time <= current_time
将是Targets.First_Time <= current_time+n
的一个子集。
numel(sorted_set_of_times)
约为40,000
numel(Targets)
超过1000万
答案 0 :(得分:1)
方法#1
带有bsxfun
-
eqcond = bsxfun(@le,Targets.First_Time,sorted_set_of_times) & bsxfun(@ge,Targets.Last_Time,sorted_set_of_times);
[r,c] = find(eqcond);
for k =1:numel(sorted_set_of_times)
target_set = r(c==k);
end
建议使用逻辑索引(如果适用):如果您使用target_set
索引到名为target
的某个变量的某个维度,这个维度很长与该维度的Targets.First_Time
相同,然后您可以使用target_set
直接索引到target
的维度,而不是计算eqcond(:,ind)
,其中ind
将是索引到该循环中的sorted_set_of_times
。因此,举例来说,如果您使用原始代码target
中的target_set
索引target(target_set,..)
行,那么您可以改为target(eqcond(:,ind),..)
。
方法#2
简化数据方法 -
vind = find(Targets.First_Time <= Targets.Last_Time); %//Indices to reduce Targets datasize
Targets.First_Time = Targets.First_Time(vind);
Targets.Last_Time = Targets.Last_Time(vind);
for current_time = sorted_set_of_times;
target_set = vind([Targets.First_Time] <= current_time & [Targets.Last_Time] >= current_time);
end
方法#3(方法#1,2的混合)
vind = find(Targets.First_Time <= Targets.Last_Time);
Targets.First_Time = Targets.First_Time(vind);
Targets.Last_Time = Targets.Last_Time(vind);
eqcond = bsxfun(@le,Targets.First_Time,sorted_set_of_times) & bsxfun(@ge,Targets.Last_Time,sorted_set_of_times);
[r,c] = find(eqcond);
for k =1:numel(sorted_set_of_times)
target_set = vind(r(c==k));
end
建议使用逻辑索引(如果适用):在类似于方法#1所述的类似讨论中,您也可以对此进行逻辑索引。因此,使用与该讨论相同的符号,而不是target(target_set,..)
,您可以执行target(vind(eqcond(:,ind)),..)
。
答案 1 :(得分:1)
我不知道具体的MATLAB指令,但您可以尝试关注,为CPU交易内存:
min_time >= TARGET.First_Time
和max_time <= TARGET.Last_Time
。答案 2 :(得分:1)
我只是在查看问题描述,我认为使用Interval Tree或KD Tree可能是您正在进行的查询类型的数据结构的更好选择。(基于搜索在范围内)。
同样地,假设您使用(startTime,EndTime)构建间隔树,然后您可以对范围执行查询。 关于此类范围查询数据结构,这是一个非常好的thread on Stackoverflow
我不知道matlab,但似乎确实支持KD-TREES。 我在matlab中找不到有关间隔树的信息,但这里有一个good tutorial。
答案 3 :(得分:1)
我认为使用这些数字,蛮力方法永远不会快得多。 (不是通过取出结构或使用逻辑索引)。
如果你想要一个快速算法,我认为以下内容可以起作用:
current_time
(已完成)First_Time
S
Last_Time
E
如果您有两个已排序的列表,您只需要遍历每个列表以找到相关点,从而显着降低操作的复杂性。
现在,您只需为每个目标调用您的函数,然后使用current_time(S:E)