matlab:高效搜索数组中的值

时间:2014-04-24 16:16:42

标签: arrays performance matlab search find

我有一组已经排序的值(例如vec = [20,54,87,233])。数组包含约300个元素。我有一个值,我需要在这个数组中搜索。成功搜索不仅是精确值,还包括范围内的+/- 5位数。例如,在这种情况下,应将17或55之类的值视为已找到。最有效的方法是什么?我使用了如下所示的循环,但我想它并没有考虑我的数组已经订购的帐户。另外,在非空的情况下,我会手动检查值是多远,因为find不返回位置。这不是一个大问题,因为我的"发现"只有15%。

bRes  = find(vec >= Value-5 & vec <= Value+5);
if ~isempty(bRes)
    distGap = GetGapDetails(Value, vec);
    return;
end

谢谢! 瓦迪姆

3 个答案:

答案 0 :(得分:1)

在已排序的列表中搜索值的最佳方法是binary search,只需O(log(n))次。这比将值与列表中的每个项目进行比较要好,费用为O(n)。据我所知,Matlab没有这方面的功能。正如Natan已经提到的,你可以(a)为此使用内置函数histc,这是用C语言编写的,可能是二进制搜索。

function good = is_within_range(value, vector, threshold)

% check that vector is sorted, comment this out for speed
assert(all(diff(vector) > 0))
assert(threshold > 0)

% pad vector with +- inf for histc
vector = [-inf, vector, inf];

% find index of value in vector, so that vector(ind) <= value < vector(ind+1)
% abuse histc, ignore bincounts
[~, ind] = histc(value, vector);

% check if we are within +- threshold from a value in vector,
% either below or above
good = (value <= vector(ind) + threshold) | value >= (vector(ind+1) - threshold);

一些快速测试:

>> is_within_range(0, [10, 30, 80], 5)
ans = 0
>> is_within_range(4, [10, 30, 80], 5)
ans = 0
>> is_within_range(5, [10, 30, 80], 5)
ans = 1
>> is_within_range(10, [10, 30, 80], 5)
ans = 1
>> is_within_range(15, [10, 30, 80], 5)
ans = 1
>> is_within_range(16, [10, 30, 80], 5)
ans = 0
>> is_within_range(31, [10, 30, 80], 5)
ans = 1
>> is_within_range(36, [10, 30, 80], 5)
ans = 0

作为奖励,此功能是矢量化的,因此您可以同时测试多个值:

>> is_within_range([0, 4, 5, 10, 15, 16, 31, 36], [10, 30, 80], 5)
ans =
     0     0     1     1     1     0     1     0

答案 1 :(得分:0)

这会更有效:

bRes  = vec >= Value-5 & vec <= Value+5;
if any(bRes) ...

你是对的,MATLAB可能不会利用&#39; vec&#39;已经排序了。你可以写一个二进制搜索到感兴趣的范围(即工作在O(log(N))时间而不是O(N)时间),但是在数组中只有300个元素,我怀疑你当前实施将很好。

答案 2 :(得分:-1)

假设你的数组存储在var'A'中,你的值是'v':

A(A>v+5 || A<v-5)=[];