2016-07-21 4 views
5

Предположим, у меня есть следующие две переменные:Эффективный оператор толстой кишки для нескольких начальных и конечных точек

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

Хочу эффективно (нет для цикла, если это возможно) генерировать одну строку, которая состоит из оператора толстой кишки между соответствующими элементами start_idx и end_idx. Для этого примера, это привело бы:

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

Поэтому:

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

Способ сделать это должны быть доступны внутри функционального блока MATLAB Simulink в. Большое спасибо!

+0

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

+0

Действительно ли arrayfun работает быстрее, чем цикл for? –

+0

Не совсем. Каковы размеры ваших векторов 'sart_idx' и' end_idx'? Я считаю, что они должны быть довольно большими для того, чтобы этот кусок кода имел невосполнимое влияние на скорость вашего кода. – BillBokeey

ответ

0

Как я указал в комментариях, один вкладыш, чтобы решить это было бы:

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

arrayfun вызов создаст массив ячеек которого каждая клетка представляет собой часть вашего выхода:

ans = 

    1  2 


ans = 

    4  5  6 


ans = 

    Columns 1 through 8 

    7  8  9 10 11 12 13 14 

    Column 9 

    15 

окружив его внутри cell2mat вызова вы получите ожидаемый результат:

out = 

    Columns 1 through 8 

    1  2  4  5  6  7  8  9 

    Columns 9 through 14 

    10 11 12 13 14 15 
+0

Анонимные функции не поддерживаются генерацией кода, поэтому я не могу использовать это в функциональном блоке MATLAB в Simulink - это требование. Спасибо за вклад, но есть ли другой способ, о котором вы можете думать? –

+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

Он должен поддерживаться для генерации кода. coder.extrinsic не поддерживается для генерации кода. –

1

Это громоздко, но, возможно, быстрее:

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); 

Он корректно обрабатывает пустые диапазоны, т.е.

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

дает

result = 
    1  2  4  5  6 
4

Вот Векторизованный подход, основанный на кумулятивном суммировании -

% 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) 

Пример запуска -

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

Если измерить истекшее время для этой части кода, после очистки рабочего пространства, вы увидите, что она занимает в среднем 0,004 секунды, а код Divakar также занимает примерно такой же количество т.е. 0,007 сек ..

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 

Как вы можете видеть, я использовал начало и конца IDX массивы большей длину и убедился, что элементы конца массива очень далеко от их соответствующих элементов начала массива.

Истекшее время, которое приходит после команды «toc», всегда изменяется в зависимости от нагрузки на CPU. Когда я измеряю время, у меня было только 1-2 приложения, кроме MATLAB, и очистило рабочее пространство перед выполнением этого код. У final_arr есть количество элементов ~ 24k, но время, затраченное на обработку выходных данных, не очень много.

Надеюсь, это поможет.

Смежные вопросы