根据起始值和终止值创建索引向量 [英] Create an index vector based on start and stop values

查看:88
本文介绍了根据起始值和终止值创建索引向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于一个矩阵,该矩阵包含索引间隔的开头(第一列)和结尾(第二列)的几行,我想创建一个包含所有索引的向量.例如,如果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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆