# How to access data in a nested structures

3 views (last 30 days)
Markus on 12 Jun 2020
Commented: KSSV on 12 Jun 2020
Hi,
how do I access parts of the following structure:
a(1).b.c = 1;
a(2).b.c = 2;
I want a vector containing the c's.
This seems to work:
vec = cat(1,cat(1,a(:).b).c);
Is this the correct way?
Why does this not work:
[a(:).b].c
Thanks!

Stephen Cobeldick on 12 Jun 2020
Edited: Stephen Cobeldick on 12 Jun 2020
"Is this the correct way?"
The usual MATLAB way is to use two lines, e.g.:
tmp = [a.b];
out = [tmp.c];
"Why does this not work: [a(:).b].c"
Because MATLAB does not allow indexing directly into the output of expressions (and accessing the field of a structure is a kind of indexing)

#### 1 Comment

Walter Roberson on 12 Jun 2020
MATLAB does not allow indexing directly into the output of expressions
It does in some cases, since R2019b:
Their attempt of
cat(1,cat(1,a(:).b).c)
is legitimate in MATLAB since R2019b: the cat(1,a(:).b) is a function call, and the output of function calls can be dot indexed now.
[a(:).b].c
Nominally that is supposed to be equivalent to
horzcat(a(:).b).c
and if you express it in horzcat form then you get a result in R2019b and later (but you would want [horzcat(a(:).b).c] to bundle the results).
But the [] to horzcat equivalence is not complete, and the [] operation is not parsed as a function call for the purpose of dot indexing. It is an inconsistency in MATLAB.

KSSV on 12 Jun 2020
[[a(:).b].c]

Markus on 12 Jun 2020
This does not work:
[[a(:).b].c]
Error: Invalid use of operator.
KSSV on 12 Jun 2020
Okay...it worked in Octave...

Walter Roberson on 12 Jun 2020
a(1).b.c = 1;
a(2).b.c = 2;
arrayfun(@(S) S.b.c, a)
The above works only if the c is always a scalar.
a(1).b.c = [-1; 1];
a(2).b.c = [-2; 2];
cell2mat(arrayfun(@(S) S.b.c, a, 'UniformOutput', false))
This version works if the number of elements in c is the same each time, and the orientation of those elements is opposite the orientation of a. In the above example, the c are column vectors and a is a row vector and the result would have the c down columns.
a(1).b.c = [-1; 1];
a(2).b.c = [-2; 2];
cell2mat(arrayfun(@(S) S.b.c(:).', a(:), 'UniformOutput', false))
This version works if the number of elements in c is the same each time (but the shape does not need to be); the elements will become rows
temp = [a.b];
[temp.c]
This version works if the c are always scalar.

Stephen Cobeldick on 12 Jun 2020
The last syntax "This version works if the c are always scalar" or any compatible sizes, e.g.:
>> a(1).b.c = [1;3;5];
>> a(2).b.c = [2;4;6];
>> temp = [a.b];
>> [temp.c]
ans =
1.00 2.00
3.00 4.00
5.00 6.00
Markus on 12 Jun 2020
Thanks for the examples and detailed explanation. For my current use case I can get away with the simple scalar version.