Accessing data in nested structure arrays
20 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
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
Respuesta aceptada
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)
Or
tmp = [a.b.c]; % comma-separated list -> concatenate scalar structures
tmp = vertcat(tmp.d); % comma-separated list -> concatenate numeric vectors
V = tmp(:,1)
4 comentarios
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(3).A(3).B(3).C(3).D % all dot indices return one array
[S1(3).A(3).B(3).C.D] % last dot index returns three arrays
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 = [tmp(1:2).B] % [two (1x3 structure) arrays]
[tmp.C] % [six (1x1 numeric) arrays]
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')
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)
Note that the indexing refers to the concatenated arrays, not the ones in the nested structure tree.
Más respuestas (0)
Ver también
Categorías
Más información sobre Matrix Indexing en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!