How to get an array of all field elements of a 1xN structure with many fields

In this thread. @Sebastian asked how to get an array of all field elements of a 1xN structure. @AdamDanz answered, but his answer only applies to a single specified field of a struct. I want be able to loop through all fields of a struct and exact all elements of each field.
For example
S(1).a = 1; S(2).a = 2 ; S(1).b = 3 ; S(2).b = 4; S(1).c = [ 1, 2]; S(2).c = [ 3, 4]
From @AdamDanz's answer, I can write
[S(:).a]
[S(:).b]
etc., but naturally one wants to be able to loop thru all fields of S, as in
Fields = fieldnames(S);
for ii= 1:numel(Fields);
field = Fields{ii};
eval(['[S(:).' field ']']);
end
There has to be a less kludgy way of doing this!!! Thanks!

1 Comment

"There has to be a less kludgy way of doing this!!! "
For a start, you can trivially remove that very ugly and inefficient EVAL by using dynamic fieldnames:
i.e. replace this slow, inefficient, complex, anti-pattern code:
eval(['[S(:).' field ']']) % ugh, do NOT do this!
with this neat, simple, and very efficient code:
[S(:).(field)]
or equivalently just this:
[S.(field)]
See also:
Using a FOR loop is probably the most efficient solution to your original question.

Sign in to comment.

 Accepted Answer

I would recommend the attached file
S(1).a = 1; S(2).a = 2 ; S(1).b = 3 ; S(2).b = 4;
T=scalarize_struct(S)
T = struct with fields:
a: [1 2] b: [3 4]

3 Comments

Thanks very much @Matt J, unfortunately my example was too simplistic, because some fields are vectors rather than scalars. I'll edit my original question to be more general. I wonder if the file
arrayify_struct
that is referred to at the top of
scalarize_struct.m
would work for the more general case? I searched for that name on the web, but couldn't find it.
scalarize_struct works for your modified example, too
S(1).a = 1; S(2).a = 2 ; S(1).b = 3 ; S(2).b = 4; S(1).c = [ 1, 2]; S(2).c = [ 3, 4];
T=scalarize_struct(S)
T = struct with fields:
a: [1 2] b: [3 4] c: {[1 2] [3 4]}
scalarize_struct woks perfectly, thanks very much!

Sign in to comment.

More Answers (1)

Fields = fieldnames(S);
for ii= 1:numel(Fields);
field = Fields{ii};
[S(:).(field)]
end
[...] is the horizontal concatenation, so the line [S(:).(field)] is equivalent to:
cat(2, S(:).(field))
Maybe you want to join the vectors vertically, then use cat(1, ...). If the arrays have different sizes, you need a cell array:
{S(:).(field)}

1 Comment

Thanks @Jan, I accepted @Matt's answer because was a bit easier to work with in my case.

Sign in to comment.

Categories

Asked:

on 2 Oct 2021

Commented:

on 3 Oct 2021

Community Treasure Hunt

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

Start Hunting!