Strcmp для массивов клеток неравной длины в MATLAB - PullRequest
6 голосов
/ 30 июня 2010

Есть ли простой способ найти меньший массив ячеек строк внутри большего? У меня есть два списка, один с уникальными элементами и один с повторяющимися элементами. Я хочу найти все вхождения конкретного шаблона меньшего массива в пределах большего. Я знаю, что strcmp будет сравнивать два массива ячеек, но только если они равны по длине. Моей первой мыслью было пройти через подмножества большего массива с помощью цикла, но должно быть лучшее решение.

Например, в следующем:

smallcellarray={'string1',...
                'string2',...
                'string3'};
largecellarray={'string1',...
                'string2',...
                'string3',...
                'string1',...
                'string2',...
                'string1',...
                'string2',...
                'string3'};

index=myfunction(largecellarray,smallcellarray)

вернется

index=[1 1 1 0 0 1 1 1]

Ответы [ 4 ]

9 голосов
/ 30 июня 2010

Вы могли бы фактически использовать функцию ISMEMBER , чтобы получить индексный вектор для того, где ячейки в largecellarray находятся в меньшем массиве smallcellarray, затем использовать функцию STRFIND (которая работает с обеими строковыми и числовыми массивами), чтобы найти начальные индексы меньшего массива в пределах большего:

>> nSmall = numel(smallcellarray);
>> [~, matchIndex] = ismember(largecellarray,...  %# Find the index of the 
                                smallcellarray);    %#   smallcellarray entry
                                                    %#   that each entry of
                                                    %#   largecellarray matches
>> startIndices = strfind(matchIndex,1:nSmall)  %# Starting indices where the
                                                %#   vector [1 2 3] occurs in
startIndices =                                  %#   matchIndex

     1     6

Тогда нужно построить вектор index из этихстартовые показатели.Вот один способ, которым вы можете создать этот вектор:

>> nLarge = numel(largecellarray);
>> endIndices = startIndices+nSmall;  %# Get the indices immediately after
                                      %#   where the vector [1 2 3] ends
>> index = zeros(1,nLarge);           %# Initialize index to zero
>> index(startIndices) = 1;           %# Mark the start index with a 1
>> index(endIndices) = -1;            %# Mark one index after the end with a -1
>> index = cumsum(index(1:nLarge))    %# Take the cumulative sum, removing any
                                      %#   extra entry in index that may occur
index =

     1     1     1     0     0     1     1     1

Другой способ создать его с помощью функции BSXFUN задается как Amro .Еще один способ создать его:

index = cumsum([startIndices; ones(nSmall-1,numel(startIndices))]);
index = ismember(1:numel(largecellarray),index);
5 голосов
/ 01 июля 2010

Вот моя версия (на основе ответов @yuk и @gnovice):

g = grp2idx([S L])';
idx = strfind(g(numel(S)+1:end),g(1:numel(S)));
idx = bsxfun(@plus,idx',0:numel(S)-1);

index = zeros(size(L));
index(idx(:)) = 1;
1 голос
/ 01 июля 2010

В ответе @gnovice первая часть может быть

l = grp2idx(largecellarray)';
s = grp2idx(smallcellarray)';
startIndices = strfind(l,s);
0 голосов
/ 30 июня 2010

У меня работает следующее решение, но я все еще задаюсь вопросом, есть ли лучший способ сделать это:

function [output]=cellstrcmpi(largecell,smallcell)
output=zeros(size(largecell));
idx=1;
while idx<=length(largecell)-length(smallcell)+1
    if sum(strcmpi(largecell(idx:idx+length(smallcell)-1),smallcell))==length(smallcell)
       output(idx:idx+length(smallcell)-1)=1;
       idx=idx+length(smallcell);       
    else
        idx=idx+1;
    end
end

(Я знаю, я знаю, без проверки ошибок - я ужасенчеловек.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...