11

Say I have the following in MATLAB:

a(1).b.c = 4;
a(2).b.c = 5;
a(3).b.c = 7;
....

I would like to collect the values [4 5 7 ...] in a single array, without looping and in a vectorized manner.

I have tried:

>> a(:).b.c 
# Error: Scalar index required for this type of multi-level indexing.

and

>> a.b.c
# Error: Dot name reference on non-scalar structure.

but they didn't work. The best I could come up with was:

arrayfun(@(x) x.b.c, a);

but as far as I understand arrayfun is not vectorized, or is it?

Community
  • 1
  • 1
Amelio Vazquez-Reina
  • 91,494
  • 132
  • 359
  • 564

3 Answers3

2

Your call to arrayfun seems idiomatic enough to me in Matlab. I don't think this is vectorized but it's well optimized and maybe the fastest way. You should also try to benchmark with a loop to see if the JIT compiler performs well here. It's hard to know without testing.

Clement J.
  • 3,012
  • 26
  • 29
2

You can do it in two lines:

>> s = [a.b];
>> y = [s.c]
y =
     4     5     7

Another possible one-liner (less readable!):

>> y = squeeze(cell2mat( struct2cell([a.b]) ))
y =
     4
     5
     7
Amro
  • 123,847
  • 25
  • 243
  • 454
1

a.b returns multiple outputs, so you can't expect to call a function on it. The best one-liner I can think of without using arrayfun is:

y = subsref([a.b], substruct('.', c));

Note that a.b.c is effectively the same as:

y = subsref(a.b, substruct('.', c))

Which is why it shouldn't work for non-scalar a.

Nzbuu
  • 5,241
  • 1
  • 29
  • 51