2016-07-21 13 views
5

Angenommen habe ich die folgenden zwei Variablen:Effiziente Doppelpunkt-Operator für mehr Start- und Endpunkte

start_idx = [1 4 7]; 
end_idx = [2 6 15]; 

ich will effizient (keine for-Schleife, wenn möglich) erzeugt eine einzelne Zeile, die von dem Doppelpunkt-Operator besteht zwischen entsprechenden Elementen von und end_idx angewendet werden. In diesem Beispiel würde dies in:

result = [1:2 4:6 7:15]; 

Deshalb:

results = [1 2 4 5 6 7 8 9 10 11 12 13 14 15]; 

Die Methode, dies zu tun, sollte in Simulink der MATLAB Funktionsblock verwendbar sein. Vielen Dank!

+0

out = cell2mat (arrayfun (@ (x, y) [x: y], start_idx, end_idx, 'uniformoutput', false)) '' – BillBokeey

+0

Ist arrayfun schneller als eine for-Schleife? –

+0

Nicht wirklich. Wie groß sind deine Vektoren 'sart_idx' und' end_idx'? Ich glaube, sie müssen ziemlich groß sein, damit dieser Code die Geschwindigkeit Ihres Codes nicht negativ beeinflusst – BillBokeey

Antwort

0

Wie ich in den Kommentaren angegeben, ein Motto zu lösen dies wäre:

out=cell2mat(arrayfun(@(x,y)[x:y],start_idx,end_idx,'uniformoutput',false)); 

Der arrayfun Aufruf eine Zellenanordnung schaffen, die jede Zelle ist ein Teil Ihrer Ausgabe:

ans = 

    1  2 


ans = 

    4  5  6 


ans = 

    Columns 1 through 8 

    7  8  9 10 11 12 13 14 

    Column 9 

    15 

Durch es in einem cell2mat Einwickeln rufen Sie die erwartete Ausgabe:

out = 

    Columns 1 through 8 

    1  2  4  5  6  7  8  9 

    Columns 9 through 14 

    10 11 12 13 14 15 
+0

Anonyme Funktionen werden von der Codegenerierung jedoch nicht unterstützt. Daher kann ich diese Funktion nicht in einem MATLAB-Funktionsblock in Simulink verwenden. Dies ist die Voraussetzung. Danke für die Eingabe, aber gibt es da noch eine andere Möglichkeit? –

+0

https://fr.mathworks.com/matlabcentral/answers/112543-how-do-i-call-an-anonymous-function-inside-the-matlab-function-block-in-simulink-8-1-r2013a – BillBokeey

+0

Es muss für die Codegenerierung unterstützt werden. coder.extrinsic wird für die Codegenerierung nicht unterstützt. –

1

Dies ist umständlich, aber vielleicht schneller:

x = min(start_idx):max(end_idx); 
m = sum(bsxfun(@ge,x,start_idx(:)),1)==numel(end_idx)-sum(bsxfun(@le,x,end_idx(:)),1)+1; 
result = x(m); 

Es richtig leeren Bereiche behandelt, dh

start_idx = [1 4 16] 
end_idx = [2 6 15]; 

result = 
    1  2  4  5  6 
4

gibt hier ein vektorisiert Ansatz auf kumulative Summe basiert -

% Get lengths of each group 
lens = end_idx - start_idx + 1; 

% Determine positions in o/p array where groups would shift 
shift_idx = cumsum(lens(1:end-1))+1 

% Initialize ID array and at shifting positions place strategically created 
% numbers, such that when ID array is cumulatively summed would result in 
% desired "ramped" array 
id_arr = ones(1,sum(lens)); 
id_arr([1 shift_idx]) = [start_idx(1) start_idx(2:end) - end_idx(1:end-1)]; 
out = cumsum(id_arr) 

Sample run -

start_idx = 
    6  8 13 
end_idx = 
    11 11 15 
out = 
    6  7  8  9 10 11  8  9 10 11 13 14 15 
1

Wenn measure die elapsed Zeit für diese piece von Code, nachdem clearing die workspace, Sie Wille see dass es takes ein average von 0,004 sec while Divakar's Code auch takes roughly die gleiche Menge dh 0,007 sec ..

start_idx=[2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44]; 
end_idx=[100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 ... 
1400 1500 1600 1700 1800 1900 2000 2100 2200]; 
tic 
final_arr=[]; 
for i=1:length(start_idx) 
final_arr=[final_arr,start_idx(i):end_idx(i)]; 
end 
toc 
final_arr 

Wie Sie sehen können, habe ich Anfang und Ende idx Arrays von größerer Länge verwendet und sorgte dafür, dass die End-Array-Elemente aus ihren jeweiligen Start Array-Elementen sehr weit entfernt sind.

Die verstrichene Zeit, die nach dem Befehl 'toc' kommt, ändert sich immer entsprechend der Belastung der CPU. Als ich die Zeit gemessen habe, hatte ich nur 1-2 Apps geöffnet, außer MATLAB und löschte den Arbeitsbereich vor der Ausführung Code. Die final_arr hat eine Anzahl von ~ 24k Elementen, aber die Zeit, die benötigt wurde, um die Ausgabe zu verarbeiten, ist nicht sehr viel.

Ich hoffe, es hilft.