2014-11-28 11 views
3

У меня есть два списка двумерных точек, заданных как M x 2 - и N x 2 - матрицы соответственно, причем M и N, возможно, очень большие.Как сравнить два несортированных списка в Matlab?

Каков самый быстрый способ определить, сколько из них одинаково?

+0

Как насчет 'size (intersect (v1, v2, 'rows'), 1)'? – matheburg

ответ

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 
0

Compute всех парных расстояний с 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); 
+0

Извините, что это, но это не очень убедительно. Это даже хуже, чем вложенные циклы, поскольку это не только O (n²) во время вычислений, но и в памяти! Вы пытались использовать мои данные с таким подходом? Компактный код не всегда лучший ответ ... – matheburg

+0

Я согласен с тем, что он компактный, но не эффективный с точки зрения памяти. В зависимости от того, какие «M» и «N» использует OP, это может быть хорошим решением или нет. –

+0

. Если вы хотите, чтобы компактное решение было лучшим вариантом для 'intersect' :) – matheburg

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 к map(key). Остальное - то же самое.

+0

Хм ... это звучит для меня как плохая версия вложенных циклов. Разве вы не должны сортировать списки перед сравнением, чтобы уменьшить общую сложность до O (nlog (n))? В противном случае ваш словарь для меня не имеет смысла. И даже если вы его сортируете, это именно то, что я делаю более эффективным способом. Я ошибаюсь? Просьба представить код, подтверждающий вашу применимость и оценку; Я уверен, что у меня тут что-то не так ... – matheburg

Смежные вопросы