2013-10-10 14 views
5

Ich bin neu in MATLAB und ich kämpfen, um die Feinheiten zwischen Array-weise und klug Element Operationen zu verstehen. Ich arbeite mit einer großen Datenmenge, und ich habe die einfachsten Methoden sind nicht immer die schnellste gefunden. Ich habe eine sehr große Zelle Array von Strings, wie in diesem vereinfachten Beispiel:Substrings aus einem Zellenfeld in Matlab

% A vertical array of same-length strings 
CellArrayOfStrings = {'aaa123'; 'bbb123'; 'ccc123'; 'ddd123'}; 

Ich versuche, eine Reihe von Teilstrings zu extrahieren, zum Beispiel:

'a1' 
'b1' 
'c1' 
'd1' 

Ich bin glücklich genug, um mit ein Element weise Referenz wie folgt:

% Simple element-wise substring operation 
MySubString = CellArrayOfStrings{2}(3:4); % Expected result is 'b1' 

aber ich kann die Notation nicht funktioniert, sie alle auf einmal zu verweisen, wie folgt aus:

% Desired result is 'a1','b1','c1','d1' 
MyArrayOfSubStrings = CellArrayOfStrings{:}(3:4); % Incorrect notation! 

Ich weiß, dass Matlab sehr schnelle Array-weise Operationen ausführen kann, wie strcat, so hoffte ich auf eine Technik, die mit einer ähnlichen Geschwindigkeit arbeitet:

% An array-wise operation which works quickly 
tic 
speedTest = strcat(CellArrayOfStrings,'hello'); 
toc % About 2 seconds on my machine with >500K array elements 

Alle die für Schleifen und Funktionen, die hinter den Kulissen Iteration verwende ich laufen zu langsam mit meinem Dataset versucht haben. Gibt es eine array-weise Notation, die das tun würde? Würde jemand in der Lage sein, mein Verständnis von elementweise und Array-weise Operationen zur Korrektur ?! Danke vielmals!

Antwort

4

Ich kann die Notation trainieren sie alle auf einmal zu verweisen, wie folgt aus:

MyArrayOfSubStrings = CellArrayOfStrings{:}(3:4); % Incorrect notation!

Dies liegt daran, geschweiften Klammern ({}) eine comma-separated list zurückkehren, das entspricht um den Inhalt dieser Zellen folgendermaßen zu schreiben:

c{1}, c{2}, and so on....

Wenn der tiefgestellte Index bezieht sich nur eine Element ermöglicht MATLAB Syntax Klammern (()) nach den geschweiften Klammern zu verwenden, und ferner eine Sub-Anordnung (ein Teilstring in diesem Fall) zu extrahieren. Diese Syntax ist jedoch verboten, wenn die durch Kommas getrennten Listen mehrere Elemente enthalten.

Also, was sind die Alternativen?

  1. Verwenden Sie eine for loop:

    MyArrayOfSubStrings = char(zeros(numel(CellArrayOfStrings), 2)); 
    for k = 1:size(MyArrayOfSubStrings, 1) 
        MyArrayOfSubStrings(k, :) = CellArrayOfStrings{k}(3:4); 
    end 
    
  2. Verwendung cellfun (eine leichte Variante von Dang Khoa's Antwort):

    MyArrayOfSubStrings = cellfun(@(x){x(3:4)}, CellArrayOfStrings); 
    MyArrayOfSubStrings = vertcat(MyArrayOfSubStrings{:}); 
    
  3. Wenn Ihre ursprüngliche Zelle Array-Strings mit einer festen Länge enthält, Sie können dem Vorschlag von Dan folgen und das Zellenarray in ein Array von Strings konvertieren (eine Matrix von ch en Charakteren), neu zu gestalten sie und extrahieren Sie die gewünschten Spalten:

    MyArrayOfSubStrings =vertcat(CellArrayOfStrings{:}); 
    MyArrayOfSubStrings = MyArrayOfSubStrings(:, 3:4); 
    
  4. Beschäftigen kompliziertere Methoden, wie reguläre Ausdrücke:

    MyArrayOfSubStrings = regexprep(CellArrayOfStrings, '^..(..).*', '$1'); 
    MyArrayOfSubStrings = vertcat(MyArrayOfSubStrings{:}); 
    

Es gibt viele Lösungen zur Auswahl, wählen Sie einfach die eine, die dir am besten passt :) Ich denke, dass mit MATLABs JIT-Beschleunigung in den meisten Fällen eine einfache Schleife ausreichen würde.

Beachten Sie auch, dass in allen meinen Vorschlägen das erhaltene Zellenfeld der Teilstrings Zelle in ein Array von Strings (eine Matrix) umgewandelt wird. Dies ist nur für das Beispiel; Natürlich können Sie die Teilstrings in einem Zellenfeld speichern, wenn Sie sich dazu entscheiden.

+1

ich danke Ihnen für Ihre umfassende Antwort, die sowohl meine Frage beantwortet als auch meinem Verständnis geholfen hat. Am Ende wählte ich Option 3, welche die beste Option für meine Datenmenge und Funktion zu sein schien: Ich fand, dass die Verwendung einer For-Schleife innerhalb meiner Funktion (Option 1) ungefähr 4x langsamer war als die Funktion mit cellfun (Option 2). Ich habe Option 3 gewählt, weil ich den anderen Jungs, die das benutzen wollen, nicht cellfun erklären muss :). Danke auch an Dan und Moshen, die ähnliche Antworten lieferten. – fodfish

+0

Kühl. Also von (1) Direktzugriff auf Zeile, Spalte, Teilzeichenfolge in einem 2d-Zellenarray, erzeugt von CellArray = textscan (fid, format) wobei col eine Textspalte wäre CellArray {col} {row} (3: 4). –

1

Sie können dies tun:

C = {'aaa123'; 'bbb123'; 'ccc123'; 'ddd123'} 
t = reshape([C{:}], 6, [])' 
t(:, 3:4) 

Aber nur, wenn Sie die Saiten alle gleich lang sind fürchte ich.

3

cellfun arbeitet auf jedem Element eines Zellenfeldes, so könnte man so etwas tun:

>> CellArrayOfStrings = {'aaa123'; 'bbb123'; 'ccc123'; 'ddd123'}; 
>> MyArrayofSubstrings = cellfun(@(str) str(3:4), CellArrayOfStrings, 'UniformOutput', false) 
MyArrayofSubstrings = 
    'a1' 
    'b1' 
    'c1' 
    'd1' 

Wenn Sie eine Matrix von Zeichenketten anstelle einer Zellenmatrix, deren Elemente die Saiten verwenden wollte char auf MyArrayOfSubstrings. Beachten Sie, dass dies nur zulässig ist, wenn jede Zeichenfolge die gleiche Länge hat.

1

Sie können char verwenden sie zu einem Zeichen-Array zu konvertieren, führen Sie die Indizierung und wandeln es wieder in Zellenfeld

A = char(CellArrayOfStrings); 
B = cellstr(A(:,3:4)); 

Beachten Sie, dass, wenn Strings unterschiedlicher Länge sind, char Pads sie mit Leerzeichen am Ende um das Array zu erstellen. Wenn Sie daher für eine Spalte indizieren, die über die Länge einer der kurzen Zeichenfolgen hinausgeht, erhalten Sie möglicherweise Leerzeichen.

Verwandte Themen