我想在更大的矩阵中分析2x2块,如果其中两个块相同,则删除它们。我试图为自己编写的代码看起来有点像这样(C是一个包含2个列的大矩阵):
n=size(C,1);
for k=1:2:(n-3)
for l=(k+2):2:(n-1)
if C(k:k+1,1:2)==C(l:l+1,1:2);
C([l,l+1],:)=[];
else
end
end
end
我遇到的问题是,matlab没有"注意"当它删除行中的C时,C的大小正在缩小。这意味着最终代码会遇到问题,因为它要求维度中的相等检查太高。我怎么能避免呢?有没有更好的方法呢?
我试图绕着"独特的"命令也是。但这只适用于行。我需要2x2段(从奇数行开始)。
此处填写(原始)代码:
A=[1,0;0,1i];
B=1/sqrt(2)*[1,1;1,-1];
C=[0,0;0,0];
C(1:2,1:2)=A(1:2,1:2);
C(3:4,1:2)=B(1:2,1:2);
for m=1:20
d=size(C,1)
C_A=C*A;
C_B=C*B;
s_a=size(C_A);
s_a=s_a(1,1);
s_b=size(C_B);
s_b=s_b(1,1);
C((d+1):(d+s_a),1:2)=C_A(1:s_a,1:2);
C((d+s_a+1):(d+s_a+s_b),1:2)=C_B(1:s_b,1:2);
n=size(C,1);
for k=1:2:(n-3)
for l=(k+2):2:(n-1)
if C(k:k+1,1:2)==C(l:l+1,1:2);
C([l,l+1],:)=[];
else
end
end
end
new_n=size(C,1)
if d==new_n
error('Done')
else
end
end
答案 0 :(得分:1)
要使代码按原样运行,请首先反转l
循环的方向:
for l = (size(C,1)-1):-2:(k+2)
这样你就可以从最后删除并在每次增加k
时重新计算最大索引。但是你仍然会遇到k
循环的麻烦,所以只需将其更改为while
循环即可。此外,使用==
比较2x2矩阵将为您提供4个值,可能不是您想要的值。如果两个矩阵具有完全相同的值,则使用isequal
将为您提供单个布尔值。
k = 1;
while (k < size(C,1))
for l = (size(C,1)-1):-2:(k+2)
if isequal(C(k:k+1,1:2), C(l:l+1,1:2))
C([l,l+1],:) = [];
end
end
k = k + 2;
end
或者,您可以通过将每个2x2子矩阵重新排列为一行来使用unique
:
D = reshape(C.', 4, []).';
U = unique(D, 'rows');
C = reshape(U.', 2, []).';
如果您正在处理浮点值,那么比较它们的平等性绝不是一个好主意;浮点值的精度有限总会给您带来麻烦。为了解决这个问题,您可以创建一个函数来比较容差内的相等性。
isequalTol=@(a,b,tol) all(abs(a-b) < tol);
此功能适用于标量,向量或矩阵。现在,您可以定义容差并将isequal
替换为isequalTol
:
tol = eps(1);
k = 1;
while (k < size(C,1))
for l = (size(C,1)-1):-2:(k+2)
if isequalTol(C(k:k+1,1:2), C(l:l+1,1:2), tol) % equal within tolerance
C([l,l+1],:) = [];
end
end
k = k + 2;
end
答案 1 :(得分:0)
与烧杯略有不同的方法,使用遮蔽来防止while循环。如果您希望稍后对重复值执行任何操作,则此方法更为可取。
CMask = ones(size(C)); %Create mask; anything with a 1 will be part of final answer, zeros will be left out
for ii = 1:2:size(C,1)
for jj = ii+2:2:size(C,1)
CMask(jj:jj+1,:) = CMask(jj,1) && ~isequal(C(ii:ii+1,:),C(jj:jj+1,:))) %If the two sections are equal, make CMask zeros in the lower section. && is required so that we don't overwrite 0s with 1s
end
end
COut = reshape(C(CMask),[],2);