如何不循环就一次索引多个数组段?

时间:2019-05-01 13:53:32

标签: matlab

我想使用另一个数组(main)的开始和结束索引,根据一个数组(conditions)中第1列的值来更改第2列中的值。
conditions的第1列中保存开始索引,在第2列中保存结束索引。

main = zeros(8, 2);
main(:, 1) = 1:8;
conditions = [2, 3; 6, 8]

main =

     1     0
     2     0
     3     0
     4     0
     5     0
     6     0
     7     0
     8     0

conditions =

     2     3
     6     8

我知道如何使用循环(如下所示)进行操作,但是我正在寻找一种更快的方法。

for ii = 1:size(conditions, 1)
    main(main(:, 1) >= conditions(ii, 1) & main(:, 1) <= conditions(ii, 2), 2) = 1;
end

main =

     1     0
     2     1
     3     1
     4     0
     5     0
     6     1
     7     1
     8     1

执行main(main(:, 1) >= conditions(:, 1) & main(:, 1) <= conditions(:, 2), 2) = 1会导致错误Matrix dimensions must agree

是否有非循环方法?

2 个答案:

答案 0 :(得分:3)

注意:这仅是整数的一种解决方案,因为原始问题仅显示了整数大小写。

首先,确定区间中包含多少个元素

dCon = diff(conditions,[],2)+1;

然后构造一个增加索引的序列,以增加元素的最大数量(对于float情况,此列表将是巨大的,因此,该解决方案不会(切实可行/有效地)扩展到floats)

idx0 = repmat(1:max(dCon),length(dCon),1);

阻止太大的索引

idx0(idx0>dCon)=1;

现在添加起点

idx = idx0 + conditions(:,1)-1;

现在idx包含您要更改的所有数字。使用ismembermain中查找所有元素并将其更改为1

main(ismember(main(:,1),idx(:)),2)=1;

编辑:这是带有注释中Gnovice的向量的完整示例

main = zeros(10, 2);
main(:, 1) = [1; 2; 2; 2; 3; 3; 4; 6; 6; 8];
conditions = [2, 3; 6, 8]
dCon = diff(conditions,[],2)+1;
idx0 = repmat(1:max(dCon),length(dCon),1);
idx0(idx0>dCon)=1;
idx = idx0 + conditions(:,1)-1;
main(ismember(main(:,1),idx(:)),2)=1;

答案 1 :(得分:3)

您的尝试几乎是正确的。如果对conditions进行转置,则将main的列与conditions的行进行比较,导致MATLAB进行隐式单例扩展,从而给出矩阵输出。然后可以使用any折叠此矩阵。

main = zeros(8, 2);
main(:, 1) = 1:8;
conditions = [2, 3; 6, 8];

index = (main(:,1) >= conditions(:, 1).') & (main(:, 1) <= conditions(:, 2).');
index = any(index,2);
main(index,2) = 1;

(为了清楚起见,我将代码分成三行,但是当然它们都可以是一行。)


请注意,对于R2016b之前的MATLAB版本,此代码将不起作用,您需要改用bsxfun

index = bsxfun(@ge,main(:,1),conditions(:, 1).') & bsxfun(@le,main(:, 1),conditions(:, 2).');