Matlab находит все ячейки, содержащие каждую строку в другом массиве ячеек, как можно быстрее

Представьте, что у вас есть две ячейки

A={'a','b','b','c','d','e'} B={'a','b','c','d','e','f'}

и вы хотите (как можно быстрее) получить ячейку индексов общих элементов

например

{1,2,2,3,4,5} индексы в элементах B

{1,[2,3],4,5,6,[]} индексы в A для элементов B

как бы ты это сделал?

2 ответа

Вот как бы я это сделал:

A = {'a','b','b','c','d','e'};
B = {'a','b','c','d','e','f'};
[~, ~, lab] = unique([A B]); % unique integer labels of elements in A and B
labA = lab(1:numel(A)); % this is A with each string replaced by its label
labB = lab(numel(A)+1:end); % this is B with each string replaced by its label
comp = bsxfun(@eq, labA(:), labB(:).'); % all pair-wise comparisons 
[ii, jj] = find(comp); % row and column indices of the matchings
result_AinB = accumarray(ii, jj, [numel(A) 1], @(x){sort(x(:).')}); % group jj by ii
result_BinA = accumarray(jj, ii, [numel(B) 1], @(x){sort(x(:).')}); % group ii by jj

Это дает

>> celldisp(result_AinB)
result_AinB{1} =
     1
result_AinB{2} =
     2
result_AinB{3} =
     2
result_AinB{4} =
     3
result_AinB{5} =
     4
result_AinB{6} =
     5

>> celldisp(result_BinA)
result_BinA{1} =
     1
result_BinA{2} =
     2     3
result_BinA{3} =
     4
result_BinA{4} =
     5
result_BinA{5} =
     6
result_BinA{6} =
     []

Лично я бы использовал

[c,ia,ib]=union(A,B)

или же

[c,ia,ib]=intersect(A,B)

и обработать индексы из этих результатов. Однако это не дает вывод в требуемом формате, поскольку в нем нет дубликатов в списке

ia = [1 2 3 4 5]

Таким образом, чтобы получить его в требуемом формате, используйте ismember дважды.

Trial>> [~,ia]=ismember(A,B)

ia =

     1     2     2     3     4     5

Trial>> [~,ib]=ismember(B,A)

ib =

     1     2     4     5     6     0

Вот почему я бы использовал объединение или пересечение, так как вы можете получить все необходимые данные за один вызов.

Если вы хотите, чтобы в этом конкретном формате, то это должно работать

ia=cellfun(@(x) find(strcmp(x,A)),B,'UniformOutput',false)
ib=cellfun(@(x) find(strcmp(x,B)),A,'UniformOutput',false)


ia =
  1×6 cell array
    [1]    [1×2 double]    [4]    [5]    [6]    [1×0 double]

ib =    
  1×6 cell array
    [1]    [2]    [2]    [3]    [4]    [5]
Другие вопросы по тегам