2016-06-19 14 views
3

Я хочу найти общие элементы в нескольких (> = 2) ячейках массивов строк.Как найти общие элементы в ячейках строк?

Связанный с этим вопрос: here, и ответ предлагает использовать функцию intersect(), однако она работает только для 2 входов.

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

c1 = {'a','b','c','d'} 
c2 = {'b','c','d'} 
c3 = {'c','d'} 
c_common = my_fun({c1,c2,c3}); 

в конце концов, я хочу c_common={'c','d'}, так как только эти две строки имеют место во всех входах.

Как это сделать с помощью MATLAB?

Спасибо заранее,

P.S. Мне также нужны индексы с каждого входа, но я, вероятно, могу сделать это сам, используя вывод c_common, поэтому в ответе не обязательно. Но если кто-то хочет, чтобы решить, что тоже, мой фактический объем производства будет выглядеть следующим образом:

[c_common, indices] = my_fun({c1,c2,c3}); 

indices = {[3,4], [2,3], [1,2]}, где для этого случая.

Спасибо,

+0

Похоже, что существует код для этого на Файлообменнике по адресу http://www.mathworks.com/matlabcentral/fileexchange/6144-mintersect-multiple-set-intersection. – edwinksl

+0

Это похоже на прямое последовательное пересечение пары ячеек, но это не особенно эффективно, как отметил автор. – edwinksl

+1

@edwinksl Большое вам спасибо! Это делает трюк, и для моей эффективности дела не очень большая проблема. Поэтому, если вы хотите опубликовать это как ответ, я соглашусь. Еще раз спасибо :) – jeff

ответ

4

Перечислены в этой должности является Векторизованным подходом, чтобы дать нам общие строки и индексы с помощью unique и accumarray. Это будет работать даже тогда, когда строки не сортируются в каждом массиве ячеек, чтобы дать нам индексы, соответствующие их положениям внутри него, но они должны быть уникальными. Пожалуйста, посмотрите пример ввода, раздел вывода *, чтобы увидеть такой запуск. Вот реализация -

C = {c1,c2,c3}; % Add more cell arrays here 

% Get unique strings and ID each of the strings based on their uniqueness 
[unqC,~,unqID] = unique([C{:}]); 

% Get count of each ID and the IDs that have counts equal to the number of 
% cells arrays in C indicate that they are present in all cell arrays and 
% thus are the ones to be finally selected 
match_ID = find(accumarray(unqID(:),1)==numel(C)); 
common_str = unqC(match_ID) 

% ------------ Additional work to get indices ---------------- 

N_str = numel(common_str); 

% Store matches as a logical array to be used at later stages 
matches = ismember(unqID,match_ID); 

% Use ismember to find all those indices in unqID and subtract group 
% lengths from them to give us the indices within each cell array 
clens = [0 cumsum(cellfun('length',C(1:end-1)))]; 
match_index = reshape(find(matches),N_str,[]); 

% Sort match_index along each column based on the respective unqID elements 
[m,n] = size(match_index); 
[~,sidx] = sort(reshape(unqID(matches),N_str,[]),1); 
sorted_match_index = match_index(bsxfun(@plus,sidx,(0:n-1)*m)); 

% Subtract cumulative group lens to give us indices corres. to each cell array 
common_idx = bsxfun(@minus,sorted_match_index,clens).' 

Пожалуйста, обратите внимание, что на этапе, который вычисляет match_ID: accumarray(unqID(:),1) может быть заменен histc(unqID,1:max(unqID)). Кроме того, histcounts будет другой альтернативой.

* ввод образца, выход -

c1 = 
    'a' 'b' 'c' 'd' 
c2 = 
    'b' 'c' 'a' 'd' 
c3 = 
    'c' 'd' 'a' 
common_str = 
    'a' 'c' 'd' 
common_idx = 
    1  3  4 
    3  2  4 
    3  1  2 
2

Как отмечалось в комментариях к этому вопросу, есть файл в файле обмена называется «MINTERSECT. - Multiple множество пересечений» на http://www.mathworks.com/matlabcentral/fileexchange/6144-mintersect-multiple-set-intersection, который содержит простой код для обобщения intersect для нескольких наборов. В двух словах код получает результат от выполнения intersect в первой паре ячеек, а затем выполняет intersect на этом выходе со следующей ячейкой. Этот процесс продолжается до тех пор, пока все клетки не будут сравниваться. Обратите внимание, что автор указывает, что код не особенно эффективен, но может быть достаточно для вашего использования.

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