Why create a 1-by-3 structure array with one field by this way?

 Accepted Answer

"Is it better than this"
Not really: both are fragile code and should be avoided.
They will both throw errors or produce unexpected results when that variable already exists in the workspace (e.g. of another class, with another size). However implicitly defining the entire array using indexing is likely to be faster.
But the recommended, easy, and robust approach to preallocate the entire structure array would be:
S = struct('a',cell(1,3))
S = 1×3 struct array with fields:
a
"Why create a 1-by-3 structure array with one field by this way"
Because it looks simpler and is less likely to scare beginners.
Because examples given in the documentation are supposed to show how things work, but are not written in terms of best code practices.
Because TMW staff are human like the rest of us.

4 Comments

Thank you very much for your help.
"They will both throw errors or produce unexpected results when that variable already exists in the workspace"-----------s(3).a=[] could produce what unexpected?
I never fan of creating array of structs via cell argument on field value.
It is an exception rule and people who don't know this rule will be very distrubed when encounting for the first time.
s = struct('a',{1 2 3});
s.a = {1 2 3}
Scalar structure required for this assignment.
s1 = struct('a',{{1 2 3}});
s2 = s1;
isequal(s1,s2)
ans = logical
1
s2.a = {{1 2 3}};
isequal(s1,s2)
ans = logical
0
% the one that works is the one that looks the less logical
s1 = struct('a',{{1 2 3}});
s2 = s1;
s2.a = {1 2 3};
isequal(s1,s2)
ans = logical
1
"s(3).a=[] could produce what unexpected?"
Probably when you looked at that code in the DEAL documentation you expected that the resulting structure has three elements in it. But as I wrote, if a structure of that name already exists then that code can have an unexpected output:
S = struct('x',num2cell(magic(4)));
% ... lots of code here
S(3).a = [] % not 3 element structure
S = 4×4 struct array with fields:
x a
New users regularly do this kind of thing: some of them expect and want this, others do not expect this because they are only partly aware of what their own code is doing or what certain operations actually do. We regularly respond to questions on this forum that are caused by users not knowing/forgetting/not checking the sizes, classes, or existence of variables in their workspaces.
Thus unexpected by certain users.

Sign in to comment.

More Answers (1)

Hi!
Let's discuss the differences between the approaches:
  1. S.a = []; This approach creates a single field a in the structure S and assigns an empty array to it. The result is that all elements of S will share the same a field.
  2. S(2).a = []; This approach creates an array of structures S, and then assigns an empty array to the a field of the 2nd structure. The other structures still have an empty a field because it wasn't explicitly assigned for them.
  3. S(3).a = []; This approach is similar to the previous one, but it assigns an empty array to the a field of the 3rd structure.
So, the main difference between the two approaches is how they handle the field a in the structures:
  • In the first approach (S.a = []), all structures in the array S share the same field a.
  • In the second approach (S(2).a = []), only the 2nd structure has the field a.
  • In the third approach (S(3).a = []), only the 3rd structure has the field a.
Which approach is better depends on your specific use case and requirements. Here is what you can look while deciding:
  • If you need all structures to have the same field a with the same value, then the first approach (S.a = [];) is more appropriate.
  • If you have specific elements in the array S that require the field a, then the second or third approach (S(2).a = []; or S(3).a = [];) can be used to assign the field only to those specific elements.
I hope this helps!
Thanks

6 Comments

"The result is that all elements of S will share the same a field."
Yes, but because S only has one element this statement is rather misleading as it implies multiple elements.
"If you need all structures to have the same field a with the same value, then the first approach (S.a = [];) is more appropriate."
Another misleading statement: this is only true if S is scalar (either scalar S exists or if S does not exist before the assignment, in which case it will be created scalar). Otherwise if S exists and is non-scalar then this code is an error:
S = struct('x',{1,2,3}) % non-scalar
S = 1×3 struct array with fields:
x
S.x = []
Scalar structure required for this assignment.
So every mention of "all structures" or "all elements" with reference to the sytnax S.a = [] is strictly correct because all of one element is indeed one element, but highly misleading becaue it appears the author thinks that that syntax refers to multiple elements of S (which it does not and cannot, as the author themselves could easily have demonstrated if thay had tested their examples before posting on this forum).
thank you very much for your help
It is confuses me is that the goal of the program is to create a 3x1 empty structure.
So,S(3).a = [];can achieve this goal at once.
S.a=[] creat 1x1 empty structure fist in memory
S(2).a=[]; creat 1x2 new structure in memory,and then copy [] from old S.a and past [] to new S structure S(1).a . Then release memory from the old S structure
S(3).a=[]; creat 1x3 new structure in memory,and then copy [] from old S(2).a and past [] to new S structure S(1).a S(2).a . Then release memory from the old 1x2 S structure
I think this is very inefficient. I don't know if my opinion is correct?
"S.a=[] creat 1x1 empty structure fist in memory"
No, a 1x1 array is not empty, it is scalar. Any array that is 1x1 is scalar: that is the definition of scalar.
The number of fields a structure array (or what their content are) is totally independent from the size of a structure array: it is possible to have an empty structure with 1000 fields. Or a 1x1000 structure with no fields.
"S(2).a=[]; creat 1x2 new structure in memory,and then copy [] from old S.a and past [] to new S structure"
Considering that structures are basically references to those numeric arrays, I doubt that MATLAB needs to copy the numeric arrays. Why would it waste time doing that? It just needs to copy the reference.
Thanks for your comment
"Considering that structures are basically references to those numeric arrays, I doubt that MATLAB needs to copy the numeric arrays"-----------I saw a matlab video, teacher said "if you know the structure size is n,you should creat S(n).xx=[]. It will make your programe run fast,because it will Pre requested memory"
Anotherway to allocate array of structure is
S = repmat(struct('a',[]), 1, 3)
S = 1×3 struct array with fields:
a
% But this will return an unexpected result for some
S = repmat(struct('a',{}), 1, 3)
S = 0×0 empty struct array with fields: a
"teacher said "if you know the structure size is n,you should creat S(n).xx=[]. It will make your programe run fast,because it will Pre requested memory""
They are certainly right that a long time ago, this approach was blazingly fast for preallocating numeric arrays. Whether it still is today, I have not checked (but given the significant changes to the JIT engine etc. I would not presume this to be still true or significant, without further testing).
In any case, preallocating numeric arrays is much more robust with ZEROS, NAN, etc.
The code I gave you here also preallocates the entire structure array, with the added benefit that it is also much more robust as well. Perhaps your teacher did not really understand how to write robust and efficient code.

Sign in to comment.

Categories

Products

Release

R2020a

Asked:

on 22 Jul 2023

Commented:

on 22 Jul 2023

Community Treasure Hunt

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

Start Hunting!