我有一个两列的矩阵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
我有一个两列的矩阵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
这里有一个量化的解决方案,我喜欢使用这个特定的问题,使用功能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
有可能是一个更好的解决方案,我不知怎么没有看到,但这里的使用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
非常怪异的解决方案恕我直言,创建临时字符串,并使用EVAL版本。也可以是单线。
tmp = cellstr(strcat(num2str(M(:,1)),{':'},num2str(M(:,2)),{' '}));
v = eval(['[' cell2mat(tmp') ']']);
我知道它可能不适用于大矩阵。只是为了好玩。
cell2mat(arrayfun(@colon,M(:,1)',M(:,2)','UniformOutput',false))
我没有IMFILL,但我的机器上这种方法比其他的快建议和我认为会因为使用find而击败IMFILL方法。
如果将M设置为置换(并且我们调整arrayfun的第三个和第四个参数),它可以变得更快。
对于输入如idxs = [1 3; 6 11; 12 12; 25000 26000],这个解决方案比gnovice更快,但OP的简单for循环仍然快得多。对于OP的示例输入,这比gnovice慢,比OP的for循环慢。 – 2015-07-21 08:23:40
是的,我知道有一个简单的解决方案。十分优雅。 +1 – yuk 2010-05-11 04:14:33
我很怀疑。 :) +1 – Jonas 2010-05-11 04:17:14
正是我正在寻找..谢谢 – merv 2010-05-11 10:28:30