我想组合两个具有不同字段名称的结构。
例如,从:
开始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
。
答案 0 :(得分:18)
没有碰撞,你可以做
M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
C=struct(M{:});
这是相当有效的。但是,重复字段名称出现struct
错误,并使用unique
对其进行预先检查会导致性能下降,导致循环更好。但这就是它的样子:
M = [fieldnames(A)' fieldnames(B)'; struct2cell(A)' struct2cell(B)'];
[tmp, rows] = unique(M(1,:), 'last');
M=M(:, rows);
C=struct(M{:});
您可以通过假设没有冲突并使用围绕调用struct
的try / catch来优雅地降级到冲突处理案例来创建混合解决方案。
答案 1 :(得分:8)
简短回答: setstructfields
(如果您有信号处理工具箱)。
官方解决方案由Loren Shure在her MathWorks blog上发布,由SCFrench here和Eitan T's answer to a different question演示。但是,如果你有信号处理工具箱,一个简单的未记录的函数已经这样做了 - setstructfields
。
<强> help setstructfields
强>
setstructfields Set fields of a structure using another structure
setstructfields(STRUCTIN, NEWFIELDS) Set fields of STRUCTIN using
another structure NEWFIELDS fields. If fields exist in STRUCTIN
but not in NEWFIELDS, they will not be changed.
在内部,它使用fieldnames
和for
循环,因此它是一个便利函数,对自身结构化的字段进行错误检查和递归。
示例强>
&#34;原作&#34;结构:
% struct with fields 'color' and 'count'
s = struct('color','orange','count',2)
s =
color: 'orange'
count: 2
包含'count'
新值的第二个结构,以及一个新字段'shape'
:
% struct with fields 'count' and 'shape'
s2 = struct('count',4,'shape','round')
s2 =
count: 4
shape: 'round'
致电setstructfields
:
>> s = setstructfields(s,s2)
s =
color: 'orange'
count: 4
shape: 'round'
字段'count'
已更新。字段'shape'
已添加。字段'color'
保持不变。
注意:由于该功能未记录,因此可能随时更改或删除。
答案 2 :(得分:5)
我找到了一个不错的solution on File Exchange: catstruct。
如果没有测试性能,我可以说它完全符合我的要求。 它当然可以处理重复的字段。
以下是它的工作原理:
a.f1 = 1;
a.f2 = 2;
b.f2 = 3;
b.f4 = 4;
s = catstruct(a,b)
会给出
s =
f1: 1
f2: 3
f3: 4
答案 3 :(得分:4)
我认为你不能在没有循环的情况下处理冲突,我认为你也不需要避免冲突。 (虽然我认为效率可能是许多领域的问题......)
我使用了几年前写的一个名为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
答案 4 :(得分:2)
在C中,struct可以将另一个struct作为其成员之一。虽然这与你提出的问题并不完全相同,但你最终可能会遇到一个结构包含另一个结构的情况,或者一个结构包含两个结构,这两个结构都包含你想要的信息的一部分。
psuedocode:我不记得实际的语法。
A.field1 = 1;
A.field2 = 'a';
A.field3 = struct B;
访问: A.field3.field4;
或类似的东西。
或者你可以让struct C同时拥有A和B:
C.A = struct A;
C.B = struct B;
访问,然后像
C.A.field1;
C.A.field2;
C.B.field3;
C.B.field4;
希望这有帮助!
编辑:这两种解决方案都避免命名冲突。
另外,我没有看到您的matlab
标记。按照惯例,您应该编辑问题以包含该信息。