为什么MATLAB对结构数组赋值中的字段顺序敏感?

MGA*_*MGA 10 arrays matlab struct matlab-struct

首先,我指定A为结构和其他两个结构:B具有相同的元素顺序,并C具有不同的元素顺序.

A.x = 11;
A.y = 11;

B.x = 21;
B.y = 22;

C.y = 31;   %// Note that I am specifying
C.x = 32;   %// y first and x second

A = B;      %// Works fine
A = C;      %// Works fine
Run Code Online (Sandbox Code Playgroud)

分配ABC工作,这是我对结构的期望 - 元素的顺序无关紧要.

现在,我指定A为结构数组,而不是一个结构,并试图转让其要素之一B,并C分别为:

clear;

A(1).x = 11;
A(1).y = 12;

B.x = 21;
B.y = 22;

C.y = 31;   %// Note that I am specifying
C.x = 32;   %// y first and x second

A(1) = B;   %// Works fine
A(1) = C;   %// Error!
Run Code Online (Sandbox Code Playgroud)

突然,MATLAB抱怨错误:

不同结构之间的下标分配

有谁知道为什么会这样,以及如何以优雅的方式解决它?

Sue*_*ver 11

这很可能发生,因为内置的subsasgn调用struct可能只是比较fieldnames源和目标结构的输出(这取决于字段顺序),并且在比较之前不执行任何排序(可能是因为性能受到影响)为每个任务排序两个单元格数组).如果存在差异(如您所示的情况),则会抛出错误并中止分配.

解决此问题的最简单方法是orderfields在源结构上使用并指定您希望使用第二个输入参数匹配目标结构的排序.

A = struct('x', 11, 'y', 12);
B = struct('y', 21, 'x', 22);

%// Ensure that the fields of B are in the same order as they are in A
A(1) = orderfields(B, A);
Run Code Online (Sandbox Code Playgroud)

在我个人看来,我认为subsasgn应该自己做struct输入,因为操作相对较快(因为没有排序,并且struct没有复制的基础数据),但允许更灵活的struct分配.

如果,另一方面,你不这样做直接分配,而只是想追加 2 structs,该字段的顺序并不重要和字段的顺序从第一继承struct所遇到的.

%// Uses the ordering of the fields in A
C = cat(1, A, B);

%// Uses the ordering of the fields in B
D = cat(1, B, A);
Run Code Online (Sandbox Code Playgroud)

更新

我刚刚注意到你在原帖中显示以下内容有效,因为订单无关紧要.

A = B;
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为此赋值不依赖于数据类型A.在这种情况下,MATLAB 删除A赋值之前引用的数据,然后 A重新分配给指向的点B.我们甚至可以创建A一个单元阵列并执行上述任务,没有任何问题.

A = cell(2);
B = struct('y', 21, 'x', 22);

%// No errors here!
A = B; 
Run Code Online (Sandbox Code Playgroud)

此赋值不会调用subsasgn(仅处理下标赋值),因此不会出现您遇到的问题.

  • 好吧,这解决了它,但它仍然感觉hacky.这对我来说似乎是MATLAB中的一个缺陷.(仍然赞成,因为它解决了这个问题) (3认同)
  • @MGA:会更方便但更慢.这将需要分类,这对于许多领域来说是昂贵的. (2认同)