2010-05-11 134 views
11

我有一个两列的矩阵M包含了一堆区间的开始/结束索引:矢量阵列创建

startInd EndInd 
1   3 
6   10 
12   12 
15   16 

我能在所有的矢量区间索引:

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

我正在做上面的使用循环,但我想知道是否有更优雅的矢量化解决方案?

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

回答

9

这里有一个量化的解决方案,我喜欢使用这个特定的问题,使用功能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

是的,我知道有一个简单的解决方案。十分优雅。 +1 – yuk 2010-05-11 04:14:33

+0

我很怀疑。 :) +1 – Jonas 2010-05-11 04:17:14

+0

正是我正在寻找..谢谢 – merv 2010-05-11 10:28:30

1

有可能是一个更好的解决方案,我不知怎么没有看到,但这里的使用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 
0

非常怪异的解决方案恕我直言,创建临时字符串,并使用EVAL版本。也可以是单线。

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

我知道它可能不适用于大矩阵。只是为了好玩。

5
cell2mat(arrayfun(@colon,M(:,1)',M(:,2)','UniformOutput',false)) 

我没有IMFILL,但我的机器上这种方法比其他的快建议和我认为会因为使用find而击败IMFILL方法。

如果将M设置为置换(并且我们调整arrayfun的第三个和第四个参数),它可以变得更快。

+1

对于输入如idxs = [1 3; 6 11; 12 12; 25000 26000],这个解决方案比gnovice更快,但OP的简单for循环仍然快得多。对于OP的示例输入,这比gnovice慢,比OP的for循环慢。 – 2015-07-21 08:23:40