2016-08-16 4 views
2

Ich habe einen Vektor, und ich möchte alle Blöcke daraus extrahieren:Extract Blöcke von Zahlen von Array in Matlab

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4] 

so dass I-Vektoren oder eine Zelle erhalten, werden die Blöcke enthalten:

[1 1 1], [4 4], [5 5], [4], [6], [1], [2], [4 4 4], [9], [8], [4 4 4 4] 

Gibt es eine effiziente Möglichkeit, dies ohne Verwendung von for-Schleifen zu tun? Vielen Dank!

+0

was ist ineffizient für for-Schleifen? – limbo

Antwort

1

Sie können accumarray mit einem benutzerdefinierten verwenden anonymous function:

y = accumarray(cumsum([true; diff(x(:))~=0]), x(:), [], @(x) {x.'}).'; 

Daraus ergibt sich eine Zellenanordnung von Vektoren. In Ihrem Beispiel

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]; 

das Ergebnis

y{1} = 
    1  1  1 
y{2} = 
    4  4 
y{3} = 
    5  5 
y{4} = 
    4 
y{5} = 
    6 
y{6} = 
    1 
y{7} = 
    2 
y{8} = 
    4  4  4 
y{9} = 
    9 
y{10} = 
    8 
y{11} = 
    4  4  4  4 
0

Für Loops nicht so langsam wie Sie vielleicht denken, vor allem nicht in neueren Matlab-Versionen und vor allem nicht in unserem Fall. Vielleicht wird dies

helfen
x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]; 

breakIdx = [0, find(diff(x)), length(x)]; 
groups = mat2cell(x,1,diff(breakIdx)); 

wir die Gruppen finden diff(x) durch die Anwendung und wir bekommen die Gruppenindizes mit find(). Dann ist es nur eine Frage der Bewegung der Gruppen in die resultierende Zelle groups.

Hier gibt es sehr wenige Edge-Case-Checks, daher empfehle ich Ihnen, das hinzuzufügen.

+1

Sie können 'groups = mat2cell (x, 1, diff (breakIdx));' verwenden, um die for-Schleife in Ihrem Code zu ersetzen, aber das würde nur die Lesbarkeit verbessern, da 'mat2cell()' selbst diese Schleife verwendet. – Finn

+0

Großer Kommentar @Finn! 'mat2cell' macht es viel sauberer :). – Algar

0

ist es, alle Blöcke in einem Zellenfeld Wenn hält nicht so wichtig, aber ruther die vollständigen Informationen über sie, können Sie diesen Code verwenden:

x = [1 1 1 4 4 5 5 4 6 1 2 4 4 4 9 8 4 4 4 4]; 
elements = x(diff([0 x])~=0); 
block_size = accumarray(cumsum(diff([0 x])~=0).',1).'; 
blocks = [elements; block_size]; 

eine 2-reihigen Matrix mit dem Element in der ersten Reihe und die Blockgröße auf der zweiten zu erhalten:

blocks = 
    1  4  5  4  6  1  2  4  9  8  4 
    3  2  2  1  1  1  1  3  1  1  4 

definieren dann eine Funktion, jene Blöcke, die durch Notwendigkeit zu erstellen:

getBlock = @(k) ones(1,blocks(2,k))*blocks(1,k); 

und nennen Sie es mit der Anzahl der Block Sie wollen:

getBlock(8) 

zu erhalten:

ans = 
    4  4  4 
Verwandte Themen