我想使用另一个数组(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
。
是否有非循环方法?
答案 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
包含您要更改的所有数字。使用ismember
在main
中查找所有元素并将其更改为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).');