SapereAude
SapereAude

Reputation: 357

In MATLAB: How should nested fields of a struct be converted to a cell array?

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

Answers (1)

nirvana-msu
nirvana-msu

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

Related Questions