Reputation: 357
In MATLAB, I would like to extract a nested field for each index of a 1 x n struct (a nonscalar struct) and receive the output as a 1 x n cell array. As a simple example, suppose I start with the following struct s:
s(1).f1.fa = 'foo';
s(2).f1.fa = 'yedd';
s(1).f1.fb = 'raf';
s(2).f1.fb = 'da';
s(1).f2 = 'bok';
s(2).f2 = 'kemb';
I can produce my desired 1 x 2 cell array c using a for-loop:
n = length(s);
c = cell(1,n);
for k = 1:n
c{k} = s(k).f1.fa;
end
If I wanted to do analogously for a non-nested field, for example f2, then I could "vectorize" the operation (see this question), writing simply:
c = {s.f2};
However the same approach does not appear to work for nested fields. What then are possible ways to vectorize the above for-loop?
Upvotes: 2
Views: 267
Reputation: 4077
You cannot really vectorize it. The problem is that Matlab does not allow most forms of nested indexing, including [].
.
The most concise / readable option would be to concatenate s.f1
results in a structure array using [...]
, and then index into the new structure array with a separate call:
x = [s.f1]; c = {x.fa};
If you have a Mapping Toolbox, you could use extractfield to perform the second indexing in one expression:
c = extractfield([s.f1], 'fa');
Alternatively you could write a one-liner using arrayfun
- here's a couple of options:
c = arrayfun(@(x) x.f1.fa, s, 'uni', false);
c = arrayfun(@(x) x.fa, [s.f1], 'uni', false);
Note that arrayfun
and similar functions are generally slower than explicit for
loops. So if the performance is critical, time / profile your code, before making a decision to get rid of the loop.
Upvotes: 2