Accessing data in nested structure arrays

76 visualizaciones (últimos 30 días)
Tim Baur
Tim Baur el 26 de Feb. de 2021
Comentada: Tim Baur el 18 de Jul. de 2022
Hi everyone,
I'm trying to access data which is nested in a structure array with multiple subfields.
I tried getfield, extractfield and multiple ways to directly access what I need
Example with what I can access easily:
a.b(1).c.d = [1 2 3];
a.b(2).c.d = [3 4 5];
a.b(3).c.d = [5 6 7];
% Direct access
>> [a.b(1).c.d]
ans =
1 2 3
% Field extraction
>> extractfield(a.b(1).c,'d')
ans =
1 2 3
% Field extraction >> only at level below array
>> extractfield(a.b,'c')
ans =
1×3 cell array
{1×1 struct} {1×1 struct} {1×1 struct}
What I' missing now is something like this which results in a vector of the first elements of d for all array entries of b (>> [1 3 5])
[a.b(:).c.d(1)]
>> [1 3 5]
Looking forward to your answers and thanks in advance!
Tim
  1 comentario
Stephen23
Stephen23 el 26 de Feb. de 2021
Editada: Stephen23 el 26 de Feb. de 2021
"Direct access": the square brackets are superfluous because you are not concatenating anything. Get rid of them.
a.b(1).c.d = [1,2,3];
a.b(2).c.d = [3,4,5];
a.b(3).c.d = [5,6,7];
a.b(1).c.d % square brackets removed
ans = 1×3
1 2 3

Iniciar sesión para comentar.

Respuesta aceptada

Stephen23
Stephen23 el 26 de Feb. de 2021
Editada: Stephen23 el 26 de Feb. de 2021
a.b(1).c.d = [1,2,3];
a.b(2).c.d = [3,4,5];
a.b(3).c.d = [5,6,7];
Either
V = arrayfun(@(s)s.c.d(1),a.b)
V = 1×3
1 3 5
Or
tmp = [a.b.c]; % comma-separated list -> concatenate scalar structures
tmp = vertcat(tmp.d); % comma-separated list -> concatenate numeric vectors
V = tmp(:,1)
V = 3×1
1 3 5
  4 comentarios
Stephen23
Stephen23 el 18 de Jul. de 2022
Editada: Stephen23 el 18 de Jul. de 2022
@Tim Baur: There is no limit to how many nested levels you can access using structure dot indexing, as long as all of those indices (except the last one) return exactly one array:
S1 = struct('A',{11,12,struct('B',{21,22,struct('C',{31,32,struct('D',{41,42,43})})})})
S1 = 1×3 struct array with fields:
A
S1(3).A(3).B(3).C(3).D % all dot indices return one array
ans = 43
[S1(3).A(3).B(3).C.D] % last dot index returns three arrays
ans = 1×3
41 42 43
As soon as any one of the other indices (not the last dot index) returns multiple items then you are generating comma-separated lists (see answer above) and you must use intermediate variables to collect/concatenate those comma-separated lists into temporary structures:
S2 = struct('A',{...
struct('B',{struct('C',{11,12,13}),struct('C',{21,22,23})}),...
struct('B',{struct('C',{31,32,33}),struct('C',{41,42,43})})});
tmp = [S2.A] % [two (1x2 structure) arrays]
tmp = 1×4 struct array with fields:
B
tmp = [tmp(1:2).B] % [two (1x3 structure) arrays]
tmp = 1×6 struct array with fields:
C
[tmp.C] % [six (1x1 numeric) arrays]
ans = 1×6
11 12 13 21 22 23
There is no specific rule for what level you need to do this at, because it depends entirely on how many (nested structure) arrays are returned by each dot index (which is not fixed, because the linear/subscript indexing can change as well as the size of the structure). Note that you can use GETFIELD to access one value of an arbitrarily nested structure:
getfield(S1,{3},'A',{3},'B',{3},'C',{3},'D')
ans = 43
While this can only get one field value, you can easily call it multiple times in a loop. Or you could write your own loop which simply keep concatenating the intermediate structures (i.e. no special treatment of comma-separated lists which only return one array) and uses your desired indexing at each level:
C = {'A','B','C';... cell array of fields and linear indices
1:2,1:2,4:5};
tmp = [S2(C{2,1}).(C{1,1})];
for k = 2:size(C,2)
tmp = [tmp(C{2,k}).(C{1,k})];
end
display(tmp)
tmp = 1×2
21 22
Note that the indexing refers to the concatenated arrays, not the ones in the nested structure tree.
Tim Baur
Tim Baur el 18 de Jul. de 2022
Great explanation, thanks!

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Matrix Indexing en Help Center y File Exchange.

Productos


Versión

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by