假设我有以下两个变量:
start_idx = [1 4 7];
end_idx = [2 6 15];
我想有效(如果可能的话,没有for循环)生成一行,该行包含在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];
执行此操作的方法应该可以在Simulink的MATLAB功能块中使用。非常感谢你!
答案 0 :(得分: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 :(得分:1)
正如我在评论中指出的那样,解决这个问题的一个方法是:
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
答案 2 :(得分: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
答案 3 :(得分: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上的负载而变化。当我测量时间时,除了MATLAB之外我只打开了1-2个应用程序并在执行此代码之前清除了工作空间。 final_arr的计数为~24k,但处理输出所需的时间并不多。
希望它有所帮助。