How to update struct array fields with mutiple values

I am trying to update a field value in a struct array. For example if I have 1*10 struct of A with a field in it called B, I want to replace the following loop with another method:
for iLoop=1:10
A(iLoop).B = iLoop;
end
I tried:
[A.B] = deal(1:10);
And also:
A = setfield(A,num2cell(1:10),'B',num2cell(1:10),(1:10));
But none of them worked (the first method assigns the whole (1:10) vector to each 'B' field in the struct array. The second one crashes). Does anyone know how to make it work?

 採用された回答

Walter Roberson
Walter Roberson 2012 年 3 月 5 日
編集済み: Walter Roberson 2019 年 9 月 19 日

5 投票

t = num2cell(1:10);
[A.B] = t{:};
See comments for the case where the struct does not already exist.

6 件のコメント

Mohammad Tabesh
Mohammad Tabesh 2012 年 3 月 5 日
I feel stupid for not having tried this one :D
Simple and Works Perfectly!
Bradley Stiritz
Bradley Stiritz 2018 年 9 月 15 日
Thank you Walter, but doesn't your solution force all the field contents to be cell values? This isn't convenient for all contexts.
Stephen23
Stephen23 2018 年 9 月 16 日
編集済み: Stephen23 2018 年 9 月 16 日
"doesn't your solution force all the field contents to be cell values?"
No, it doesn't. The LHS has nothing to do with any cell arrays. Both the LHS and RHS use comma-separated lists, which happen to be defined using a non-scalar structure and a non-scalar cell array respectively. No field/element/value of the LHS is "forced" to be a cell array, which you can easily check yourself:
>> V = 1:10;
>> C = num2cell(V);
>> [A.B] = C{:};
>> A(1).B
ans = 1
>> class(A(1).B)
ans = double
Do you see any cell array anywhere in A or its fields? I don't.
You can learn about comma-separated lists here:
Your comment and five-star rating to this FEX submission
is interesting, as it does exactly the same thing as Walter Roberson's answer. Lets try it:
>> [S.B] = disperse(V);
>> S(1).B
ans = 1
>> class(S(1).B)
ans = double
Exactly the same as Walter Roberson's answer above. There is absolutely no difference.
Walter Roberson
Walter Roberson 2018 年 9 月 16 日
Note: better is
[A(1:length(t)).B] = t{:};
breathi
breathi 2019 年 9 月 19 日
Walter,
please edit your answer and insert the solution you posted in the comments.
It was driving me nuts to find out, that only an existing struct array can be filled with your current solution, just to find out a few angry debug steps later that you posted a comment and that this solution could just create a new struct array by explicitly using length(t) as the left side input.
Thanks.
Walter Roberson
Walter Roberson 2019 年 9 月 19 日
For the case where the struct does not already exist, there is a different method that can be easier:
A = struct('B', t);
where t is the cell array from above. This also permits you to store to multiple fields, and to leave some fields empty, and to put in non-scalar values.
A = struct('B', num2cell(1:10), 'C', [], 'D', num2cell(rand(2,10),1));

サインインしてコメントする。

その他の回答 (3 件)

Andrew Newell
Andrew Newell 2012 年 3 月 5 日

0 投票

What timing! It happens that the File Exchange Pick of the Week is the function disperse. If you download disperse and put it on your path, you can use the following command:
[A.B] = disperse(1:10);

3 件のコメント

Mohammad Tabesh
Mohammad Tabesh 2012 年 3 月 5 日
Thank you for your help but Walter's suggestion works perfectly and does not need any functions.
Bradley Stiritz
Bradley Stiritz 2018 年 9 月 15 日
Thank you Andrew! disperse() is just what I needed.
Stephen23
Stephen23 2018 年 9 月 16 日
編集済み: Stephen23 2018 年 9 月 16 日
"disperse() is just what I needed."
Actually Walter Roberson's answer does exactly the same thing, without requiring third-party functions.

サインインしてコメントする。

Tom
Tom 2018 年 2 月 12 日
編集済み: Tom 2018 年 2 月 12 日

0 投票

This works perfectly, until you have a field in between.
[A.B] = t{:}; %Great!
[A.B(1).C] = t{:}; % doesn't work
Anyone have a suggestion on how to make it work this way?

1 件のコメント

Mohammad Tabesh
Mohammad Tabesh 2018 年 2 月 13 日
If your question structure is that A has 10 rows, each have a field B which in turn has a field C that you want to update, I suggest creating an intermediate structure array similar to B, assign the values there and then assign that to field B:
D = A.B;
[D.C] = t{:};
[A.B] = deal(D);

サインインしてコメントする。

Mitja M
Mitja M 2018 年 7 月 25 日

0 投票

I would highly appreciate the solution to the following problem, which I believe is highly related to the previous, but I somehow don't find the appropriate solution.
I have the following variables:
AA, 1×3 struct array with fields: bb
bb, nx6 double array
cc, nx3 double array
n for all three bb and cc arrays is equal to 100 right now
Now I would like to change the fifth column of all three bb arrays to corresponding column in cc array. It can be correctly done using the following for loop:
for i=1:3
AA(i).bb(:,5)=cc(:,i);
end
Is it possible to achieve this without the for loop.
Thank you

1 件のコメント

Mohammad Tabesh
Mohammad Tabesh 2018 年 7 月 26 日
Hi Mitja, I suggest a similar approach as I suggested to Tom.
BB=cat(3,AA.bb);
BB(:,5,:)=cc;
BBB=num2cell(BB,[1 2]);
[AA.bb]=deal(BBB{:});

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeCell Arrays についてさらに検索

製品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by