我有一组已经排序的值(例如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
谢谢! 瓦迪姆
答案 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)=[];