即使字段内容被转置,检查两个 MATLAB 结构是否相等

Checking two MATLAB structs as equal even if field contents are transposed

我需要检查两个 MATLAB 结构(所有字段名和值)是否相等。这两个结构都是结构的结构。有时,这些结构除了一件事外是相等的:一个结构中的字段值是另一个结构中字段值的转置。

如果我使用函数 isequal 检查两个结构是否相等,如果字段内容被转置,我会得到一个否定的结果。

示例:

cfg1.x = {'a' 'b'};
cfg1.y.z = {'c' 'd'};

cfg2.x = {'a' 'b'}';
cfg2.y.z = {'c' 'd'}';

isequal(cfg1, cfg2)

>> isequal(cfg1, cfg2)

ans =

  logical

   0

一种解决方案是在检查相等性之前,我可以遍历一个结构的字段,并在必要时通过转置确保大小调整与另一个结构的字段对齐。然而,这似乎不是很有效,我喜欢尽可能避免循环。有没有类似于isequal的转置不变的函数?

前段时间我自己编写了嵌套结构的递归比较(主要是为了查看变量的不同之处),您只需在代码的一行中将 isequal(a,b) 替换为 isequal(a,b) || isequal(a,b') 即可获得转置不变的 isequal 行为。如果两个变量不相等,代码会抛出错误,并指出 where.

function compare(A, B, path)
% Compares two variables, A and B, for equality with a recursive test.
% Throws and error if not equal, otherwise just returns.

assert(nargin >= 2, 'Not enough parameters.');
if nargin == 2
    path = '';
end

their_class = class(A);

assert(strcmp(their_class, class(B)), '%s, A and B do not have the same class.', path);

if isnumeric(A) || islogical(A)
    % here we also treat NaN as equal since we compare the content of two variables
    assert(isequaln(A, B), '%s, Array A and B are not equal.', path);
    % replace isequaln(A, B) with isequaln(A, B) || isqualn(A, B') to get transpose-invariance of comparison
else

    switch their_class
        case 'cell'
            compare_cells(A, B, path);
        case 'struct'
            compare_structs(A, B, path);
        case 'char'
            assert(strcmp(A, B), '%s, Char array A and B is not equal.', path);
        otherwise
            error('%s, Comparison of class %s not yet supported.', path, their_class);
    end
end

end

function compare_cells(A, B, path)
% Assuming A and B are both cell array, compare them, calling back to the
% main function if needed.

assert(isequal(size(A), size(B)), 'Size of cell arrays not equal.');

for i = 1 : numel(A)
    compare(A{i}, B{i}, [path, sprintf('/cell:%d', i)]);
end

end

function compare_structs(A, B, path)
% Assuming A and B are both structs, compare them, calling back to the main
% function if needed.

fields = fieldnames(A);

assert(all(strcmp(unique(fields), unique(fieldnames(B)))), 'Number of names of struct fields not equal.');

for i = 1 : length(fields)
    field = fields{i};
    a = A.(field);
    b = B.(field);
    compare(a, b, [path, sprintf('/field:%s', field)]);
end

end