【发布时间】:2014-11-29 18:51:42
【问题描述】:
我有两个二维点列表,分别为 M x 2 - 和 N x 2 - 矩阵,其中 M 和 N 可能非常大。
确定其中有多少相等的最快方法是什么?
【问题讨论】:
-
size(intersect(v1,v2,'rows'),1)呢?
标签: matlab
我有两个二维点列表,分别为 M x 2 - 和 N x 2 - 矩阵,其中 M 和 N 可能非常大。
确定其中有多少相等的最快方法是什么?
【问题讨论】:
size(intersect(v1,v2,'rows'),1) 呢?
标签: matlab
我不确定您是否要计算重复条目,但如果不是,您可以使用intersect 或一些基于排序的非常直观的算法(见下文)。我不喜欢嵌套循环版本...
function test_compareVecs()
%% create some random data
N = 31415;
M1 = 100000;
M2 = 200000;
vec = rand(N,2);
v1 = [rand(M1-N,2); vec];
v2 = [rand(M2-N,2); vec];
v1 = v1(randperm(M1),:);
v2 = v2(randperm(M2),:);
%% intersect
disp('intersect:');
tic
s = size(intersect(v1,v2,'rows'),1);
toc;
s
%% alternative approach
disp('alternative approach:');
tic;
s = compareVecs(v1,v2);
toc;
s
end
function s = compareVecs(v1,v2)
%% create help vector
help_vec = [[v1,zeros(size(v1,1),1)]; ...
[v2,ones(size(v2,1),1)]];
%% sort by first column
% note: for some reason "sortrows(help_vec,1)" is slower
hash_vec = help_vec(:,1); % dummy hash
[~,sidx] = sort(hash_vec);
help_vec = help_vec(sidx,:);
%% diff + compare
help_vec = diff(help_vec);
s = sum(help_vec(:,1) == 0 & ...
help_vec(:,2) == 0 & ...
help_vec(:,3) ~= 0);
end
结果
intersect:
Elapsed time is 0.145717 seconds.
s = 31415
alternative approach:
Elapsed time is 0.048084 seconds.
s = 31415
【讨论】:
使用pdist2 计算所有成对距离,然后计算距离为零的对。如果坐标是浮点值,您可能希望使用容差而不是与零进行比较:
%// Data:
M = 10;
N = 8;
listM = randi(10,M,2)-1;
listN = randi(10,N,2)-1;
tol = 1e-6;
%// Distance matrix:
d = pdist2(listM, listN);
%// Count:
count = sum(d(:)<tol);
【讨论】:
M 和 N,它可能是一个很好的解决方案
intersect one-liner 是更好的选择 :)
无论每个列表中点的顺序或长度如何,这都应该有效。它是一种哈希表/字典解决方案,应该很快,但内存需求与列表的长度成线性关系。请注意,下面的语法可能并不完美,但快速参考提到的主要数据结构应该可以轻松进行更正。
(1) 填充一个类似字典的containers.Map,其中键是点的唯一函数,例如num2str(M(i,1))'-'num2str(M(i,2)).
(2) 然后,遍历第二个列表的所有元素,像 (1) 中一样创建键并检查它是否存在。如果是,则设置map(key)=1,否则设置为0。最后,所有由公共点组成的键都将存储1,其余的将为零。
(3) 通过对地图的值求和(类似于sum(map.values()))来完成,这应该为您提供两组之间唯一交叉点的总数,而不管这些点的顺序如何出现在每个列表中。
OBS:如果您不想只计算唯一的交叉点而是所有重复点,请在 (2) 中,而不是创建 map(key)=1,将 1 添加到 map(key)。其余的都是一样的。
【讨论】: