11 Stimmen

Vektorisierte Array-Erstellung aus einer Liste von Start-/Endindizes

Ich habe eine zweispaltige Matrix M die die Start-/Endindizes eines Bündels von Intervallen enthält:

startInd   EndInd
1          3
6          10
12         12
15         16

Wie kann ich einen Vektor mit allen Intervallindizes erstellen?

v = [1 2 3 6 7 8 9 10 12 15 16];

Ich tue die oben mit Schleifen, aber ich frage mich, wenn es eine elegantere vektorisierte Lösung?

v = [];
for i=1:size(M,1)
    v = [v M(i,1):M(i,2)];
end

9voto

gnovice Punkte 124264

Hier ist eine vektorisierte Lösung, die ich gerne für dieses spezielle Problem verwende, unter Verwendung der Funktion cumsum :

v = zeros(1, max(endInd)+1);  % An array of zeroes
v(startInd) = 1;              % Place 1 at the starts of the intervals
v(endInd+1) = v(endInd+1)-1;  % Add -1 one index after the ends of the intervals
v = find(cumsum(v));          % Perform a cumulative sum and find the nonzero entries

0 Stimmen

Y

1 Stimmen

N

6voto

MatlabSorter Punkte 1270
cell2mat(arrayfun(@colon,M(:,1)',M(:,2)','UniformOutput',false))

Ich habe kein IMFILL, aber auf meinem Rechner ist diese Methode schneller als die anderen Vorschläge und ich denke, dass sie die IMFILL-Methode aufgrund der Verwendung von find schlagen würde.

Es kann sogar noch schneller gehen, wenn M transponiert eingerichtet wird (und wir das dritte und vierte Argument von arrayfun anpassen).

1 Stimmen

F

1voto

Jonas Punkte 74252

Wahrscheinlich gibt es eine noch bessere Lösung, die ich irgendwie nicht sehe, aber hier ist eine Version mit IMFILL

startInd = [1,6,12,15];
endInd = [3,10,12,16];

%# create a logical vector with starts and ends set to true to prepare for imfill
tf = false(endInd(end),1);
tf([startInd,endInd]) = true;

%# fill at startInd+1 wherever startInd is not equal endInd
tf = imfill(tf,startInd(startInd~=endInd)'+1); %' SO formatting

%# use find to get the indices
v = find(tf)'  %' SO formatting

v =
     1     2     3     6     7     8     9    10    12    15    16

0voto

yuk Punkte 18683

Sehr seltsame Lösung IMHO Erstellung von temporären Zeichenfolgen und Verwendung von EVAL. Kann auch ein Einzeiler sein.

tmp = cellstr(strcat(num2str(M(:,1)),{':'},num2str(M(:,2)),{' '}));
v = eval(['[' cell2mat(tmp') ']']);

Ich weiß, dass es bei einer großen Matrix wahrscheinlich nicht funktionieren wird. Nur zum Spaß.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X