我有两个二维点列表,分别为M x 2 - 和N x 2 - 矩阵,M和N可能非常大。
确定其中有多少相等的最快方法是什么?
答案 0 :(得分:2)
我不确定您是否要计算重复条目,但如果不是,您可以使用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
答案 1 :(得分:0)
使用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);
答案 2 :(得分:0)
无论每个列表中的点的顺序或长度如何,这都应该起作用。它是一个哈希表/字典解决方案应该很快但内存需求与列表的长度成线性关系。请注意,下面的语法可能并不完美,但是对所提到的主要数据结构的快速参考应该会使修正变得微不足道。
(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}添加1 }}。其余的都一样。