2017-06-02 58 views
9

我想重新排列結構如下:插入中間水平爲嵌套結構數組

%// 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,但沒有什麼工作,只要始終需要一個標量structur。有一些我忽略的功能嗎?

回答

2

一種選擇是使用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{:}; 
+0

這兩個選項都非常好!我發現我必須學習更多關於setfield函數的用法。 – thewaywewalk

2

通過先分配y=s,我們可以跳過if-else語句,也拆除for循環中的一個。如果我們想要,我們可以添加另一個for循環以允許fieldToMovenewFieldname爲單元陣列,從而移動多個字段。請注意,如果您只對移動單個字段的情況感興趣,則可以刪除內部的for-loop。

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 
+0

我其實是有點慚愧沒有關於這種簡化的思想;)謝謝! – thewaywewalk

3

使用的struct + num2cell的組合可以做到這一點

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

謝謝!它需要知道「a」(可能還有其他人)。所以我寧願用更通用的gnovice方法。 – thewaywewalk