根据起始值和终止值创建索引向量 [英] Create an index vector based on start and stop values
问题描述
基于一个矩阵,该矩阵包含索引间隔的开头(第一列)和结尾(第二列)的几行,我想创建一个包含所有索引的向量.例如,如果A = [2 4; 8 11 ; 12 16]
,我想具有以下向量index = [2 3 4 8 9 10 11 12 13 14 15 16]
.
Based on a matrix which contains several rows of the beginning (first column) and the end (second column) of an interval of index, I would like to create a vector of all the index. For instance, if A = [2 4; 8 11 ; 12 16]
, I would like to have the following vector index = [2 3 4 8 9 10 11 12 13 14 15 16]
.
我正在寻找最快的方法.目前,我仅发现两种可能性:
I'm looking for the fastest way to do that. For now, I found only two possibilities:
1)循环
index = [];
for n = 1:size(A, 1)
index = [index A(n, 1):A(n, 2)];
end
2)和arrayfun
index = cell2mat(arrayfun(@(n) A(n, 1):A(n, 2), 1:size(A, 1), 'uni', 0));
有趣的是,arrayfun
比循环版本快得多,我不知道为什么.另外,我使用从单元到垫的转换,所以很奇怪.您如何看待?您还有其他建议吗?
Interestingly, arrayfun
is much faster than the loop version, and I don't know why. Plus I use a conversion from cell to mat, so that's weird. What do you think about that? Do you have another suggestions?
感谢您的帮助
推荐答案
以下是方法的集合:
方法1 ,来自 https://stackoverflow.com/a/39422485/6579744 :
lo = A(:,1);
up=A(:,2);
index=cumsum(accumarray(cumsum([1;up(:)-lo(:)+1]),[lo(:);0]-[0;up(:)]-1)+1);
index= index(1:end-1);
方法2:这是从 https://stackoverflow.com/a/38507276/6579744 .我也提供了相同的答案,但是因为Divakar的答案要早于我的(修改后的)答案:
Method 2: this is from https://stackoverflow.com/a/38507276/6579744 . I also provided the same answer but because Divakar's answer is before mine his (modified) answer preferred:
start_idx = A(:,1)';
end_idx = A(:,2)';
lens = end_idx - start_idx + 1;
shift_idx = cumsum(lens(1:end-1))+1;
id_arr = ones(1,sum(lens));
id_arr([1 shift_idx]) = [start_idx(1) start_idx(2:end) - end_idx(1:end-1)];
index = cumsum(id_arr);
方法3:这是我的
N = A(:,2) - A(:,1) +1;
s=cumsum([ 1; N]);
index=(1:s(end)-1) -repelem(s(1:end-1),N) + repelem(A(:,1),N);
%octave index=(1:s(end)-1) -repelems(s(1:end-1),[1:numel(N);N']) + repelems(A(:,1),[1:numel(N);N']);
方法4 : thewaywewalk
A = A.';
idx = bsxfun(@plus, A, [0; 1]);
A = A(:);
dA = diff(A); dA(1:2:end) = 0;
idx = idx(~( [0;dA] == 1 | [dA;0] == 1 ));
mask = zeros(max(A),1);
mask(idx(:)) = (-1).^(0:numel(idx)-1);
index = find(cumsum(mask));
方法5 :第二种方法:
index = cell2mat(arrayfun(@(n) A(n, 1):A(n, 2), 1:size(A, 1), 'uni', 0));
方法6 ,来自 https://stackoverflow.com/a/39423102/6579744 :
sz= size(A, 1);
index_c = cell(1,sz);
for n = 1:sz
index_c{n} = [A(n, 1):A(n, 2)];
end
index = cell2mat(index_c);
方法7 仅适用于八度:
idx = 1:size(A ,1);
index_a =bsxfun(@(a,b) (a(b):A (b,2))',A (:,1),idx);
index = index_a(index_a ~= 0);
方法8 :您的第一种方法:
index = [];
for n = 1:size(A, 1)
index = [index A(n, 1):A(n, 2)];
end
测试数据:
i= 1:500:10000000;
j= i+randi([1 490],1, numel(i));
A = [i', j'];
结果在Octave中进行了测试,在Matlab中可能有所不同
Result tested in Octave, in Matlab may be different
method1: 0.077063 seconds
method2: 0.094579 seconds
method3: 0.145004 seconds
method4: 0.180826 seconds
method5: 0.317095 seconds
method6: 0.339425 seconds
method7: 3.242287 seconds
method8: doesn't complete in 15 seconds
bechmark中使用的代码位于> 在线演示
the code that used in bechmark is in Online Demo
这篇关于根据起始值和终止值创建索引向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!