在MATLAB中结合两种结构的有效方法有哪些?

时间:2020-03-05 18:46:11  来源:igfitidea点击:

我想结合两个具有不同字段名称的结构。

例如,从以下开始:

A.field1 = 1;
A.field2 = 'a';

B.field3 = 2;
B.field4 = 'b';

我想拥有:

C.field1 = 1;
C.field2 = 'a';
C.field3 = 2;
C.field4 = 'b';

有没有比使用" fieldnames"和for循环更有效的方法?

编辑:让我们假设在字段名冲突的情况下,我们优先考虑A

解决方案

回答

在C语言中,一个结构可以拥有另一个结构作为其成员之一。尽管这与我们要求的不完全相同,但是我们可能会遇到以下情况:一个结构包含另一个结构,或者一个结构包含两个结构,这两个结构都包含我们想要的部分信息。

psuedocode:我不记得实际的语法。

A.field1 = 1;
A.field2 = 'a';
A.field3 = struct B;

访问:
A.field3.field4;

或者类似的东西。

或者,我们可以让结构C同时持有A和B:

C.A = struct A;
C.B = struct B;

具有访问权限,然后像

C.A.field1;
C.A.field2;
C.B.field3;
C.B.field4;

希望这可以帮助!

编辑:这两个解决方案都避免了命名冲突。

另外,我也没有看到matlab标签。按照惯例,我们应该要编辑问题以包括该信息。

回答

没有碰撞,我们可以

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
C=struct(M{:});

这是相当有效的。但是,重复字段名上的"结构"错误,并使用"唯一"进行预检查会导致性能下降,从而使循环更好。但是,结果如下所示:

M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];

[tmp, rows] = unique(M(1,:), 'last');
M=M(:, rows);

C=struct(M{:});

我们可以通过假设没有冲突,并在对struct的调用周围使用try / catch来优雅地降级到冲突处理情况,从而做出混合解决方案。

回答

我认为我们无需循环就可以很好地处理冲突,也不必避免冲突。 (尽管我认为效率可能是很多领域的问题...)

我使用了几年前写的一个名为" setdefaults.m"的函数,该函数将一个结构与另一个结构的值组合在一起,在发生冲突时,其中一个优先于另一个。

% SETDEFAULTS sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 
%    SOUT = SETDEFAULTS(S, SDEF, OVERRIDE) does
%    the same function as above, but if OVERRIDE is 1,
%    it copies all fields of SDEF to SOUT.

function sout = setdefaults(s,sdef,override)
if (not(exist('override','var')))
    override = 0;
end

sout = s;
for f = fieldnames(sdef)'
    cf = char(f);
    if (override | not(isfield(sout,cf)))
        sout = setfield(sout,cf,getfield(sdef,cf));
    end
end

现在,我考虑了一下,虽然我不确定100%的肯定,但是我很确定"覆盖"输入是不必要的(我们可以只切换输入的顺序)。因此,这是一个更简单的重写( setdefaults2.m):

% SETDEFAULTS2 sets the default structure values 
%    SOUT = SETDEFAULTS(S, SDEF) reproduces in S 
%    all the structure fields, and their values,  that exist in 
%    SDEF that do not exist in S. 

function sout = setdefaults2(s,sdef)
sout = sdef;
for f = fieldnames(s)'
    sout = setfield(sout,f{1},getfield(s,f{1}));
end

和一些样品进行测试:

>> S1 = struct('a',1,'b',2,'c',3);
>> S2 = struct('b',4,'c',5,'d',6);
>> setdefaults2(S1,S2)

ans = 

    b: 2
    c: 3
    d: 6
    a: 1

>> setdefaults2(S2,S1)

ans = 

    a: 1
    b: 4
    c: 5
    d: 6