矢量化冒号(:)的概念 - 在MATLAB中两个向量之间的值

时间:2013-01-15 16:06:32

标签: matlab vector vectorization colon

我有两个向量,idx1idx2,我想获取它们之间的值。如果idx1idx2是数字而不是向量,我可以通过以下方式执行此操作:

idx1=1;
idx2=5;
values=idx1:idx2 

% Result
 % values =
 % 
 %    1     2     3     4     5

但就我而言,idx1idx2是可变长度的向量。例如,长度= 2:

idx1=[5,9];
idx2=[9 11];

我可以使用冒号运算符直接获取其间的值吗?这类似于以下内容:

values = [5     6     7     8     9     9    10    11]

我知道我可以做idx1(1):idx2(1)idx1(2):idx2(2),这就是,分别提取每列的值,所以如果没有其他解决方案,我可以用for循环来做,但是也许Matlab可以更轻松地做到这一点。

4 个答案:

答案 0 :(得分:11)

您的示例输出不合法。矩阵不能有不同长度的行。你可以做的是使用arrayfun创建一个单元格数组:

values = arrayfun(@colon, idx1, idx2, 'Uniform', false)

要将生成的单元格数组转换为矢量,可以使用cell2mat

values = cell2mat(values);

或者,如果结果单元格数组中的所有向量具有相同的长度,则可以按如下方式构造输出矩阵:

values = vertcat(values{:});

答案 1 :(得分:0)

尝试使用集合的联合。根据您提供的idx1idx2的值,运行

values = union(idx1(1):idx1(2), idx2(1):idx2(2));

根据需要,将生成值为[5 6 7 8 9 10 11]的向量。

答案 2 :(得分:0)

我无法让@ Eitan的解决方案工作,显然你需要为冒号指定参数。接下来的小修改使它在我的R2010b版本上工作:

step = 1; 
idx1 = [5, 9];
idx2 = [9, 11];
values = arrayfun(@(x,y)colon(x, step, y), idx1, idx2, 'UniformOutput', false);
values=vertcat(cell2mat(values));

请注意,step = 1实际上是colon中的默认值,而Uniform可用于代替UniformOutput,但我为了完整性。

答案 3 :(得分:0)

Loren 有一篇名为Vectorizing the Notion of Colon (:)的精彩博文。它包含的答案比使用arrayfunfor循环快大约5倍(对于大型数组),类似于运行长度解码:

  

这个想法是扩大结肠序列。我知道的长度   每个序列,所以我知道输出数组中的起点。填   起始值后的值为1s。然后我弄明白了多少   从一个序列的末尾跳到下一个序列的开头。   如果有重复的起始值,则跳转可能为负。一旦   这个数组被填充,输出只是累积和或   cumsum序列。

function x = coloncatrld(start, stop)
% COLONCAT Concatenate colon expressions
%    X = COLONCAT(START,STOP) returns a vector containing the values
%    [START(1):STOP(1) START(2):STOP(2) START(END):STOP(END)].

% Based on Peter Acklam's code for run length decoding.
len = stop - start + 1;

% keep only sequences whose length is positive
pos = len > 0;
start = start(pos);
stop = stop(pos);
len = len(pos);
if isempty(len)
    x = [];
    return;
end

% expand out the colon expressions
endlocs = cumsum(len);  
incr = ones(1, endlocs(end));  
jumps = start(2:end) - stop(1:end-1);  
incr(endlocs(1:end-1)+1) = jumps;
incr(1) = start(1);
x = cumsum(incr);