2010-05-11 131 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