【问题标题】:Insert intermediate level into nested struct array将中间级别插入嵌套结构数组
【发布时间】:2017-11-03 23:00:29
【问题描述】:

我想按如下方式重新排序结构:

%// original struct
s(1).a = rand(10,1);
s(2).a = rand(10,1);
s(1).b = rand(10,1);
s(2).b = rand(10,1);

%// reorder to:
y(1).a = s(1).a;
y(2).a = s(2).a;
y(1).b.c = s(1).b;
y(2).b.c = s(2).b;

以下嵌套循环有效:

fieldToMove = 'b';
newFieldname = 'c';

fn = fieldnames(s);

for ii = 1:numel(fn)

    for jj = 1:numel(s)
        if strcmp(fn{ii},fieldToMove)
            y(jj).(fn{ii}).(newFieldname) = s(jj).(fn{ii});
        else
            y(jj).(fn{ii}) = s(jj).(fn{ii});
        end
    end
end

但这对我来说似乎有点过头了。任何想法如何优化或简化它?


我对临时值进行了很多实验,用rmfield 删除了原始字段,并用setfield 设置了新字段,但到目前为止,没有任何效果,因为始终需要标量结构。有没有我忽略的功能?

【问题讨论】:

    标签: matlab struct vectorization


    【解决方案1】:

    通过预先分配y=s,我们可以跳过 if-else 语句并删除其中一个 for 循环。如果需要,我们可以添加另一个 for 循环以允许 fieldToMovenewFieldname 成为元胞数组,从而移动多个字段。请注意,如果您只对移动单个字段的情况感兴趣,则可以删除内部 for 循环。

    s(1).a = rand(10,1);
    s(2).a = rand(10,1);
    s(1).b = rand(10,1);
    s(2).b = rand(10,1);
    s(1).d = rand(10,1);
    s(2).d = rand(10,1);
    
    fieldsToMove = {'b','d'};
    newFieldnames = {'c','e'};
    
    y = s;
    for ii = 1:numel(y)
        for jj = 1:numel(fieldsToMove)
            y(ii).(fieldsToMove{jj}) = struct(newFieldnames{jj},s(ii).(fieldsToMove{jj}));
        end
    end
    

    【讨论】:

    • 我其实有点惭愧没有考虑过这种简化;)谢谢!
    【解决方案2】:

    使用struct + num2cell 的组合可以做到这一点

    y = struct('a', {s.a}, 'b', num2cell(struct('c', {s.b})));
    

    【讨论】:

    • 谢谢!不过,它需要'a'(可能还有其他人)的知识。所以我宁愿使用更通用的 gnovice 方法。
    【解决方案3】:

    一种选择是像这样使用arrayfunsetfield

    y = s;
    y = arrayfun(@(s) setfield(s, 'b', struct('c', s.b)), y);
    

    另一种选择是distribute 修改字段b

    y = s;
    temp = num2cell(struct('c', {y.b}));
    [y.b] = temp{:};
    

    【讨论】:

    • 两个选项都很好!我知道我必须更多地了解 setfield 函数的用法。
    猜你喜欢
    • 2022-06-10
    • 1970-01-01
    • 2015-11-26
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 2019-12-14
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多