Create array of “deep” struct (scalar) fields

4 Ansichten (letzte 30 Tage)
Jorge
Jorge am 11 Aug. 2019
Beantwortet: Jorge am 12 Aug. 2019
Hi! How can I collapse the values of "deep" struct fields into arrays by just indexing?
In the example below, I can only do it for the "top-most" level, and for "deeper" levels I get the error:
"Expected one output from a curly brace or dot indexing expression, but there were XXX results."
The only workaround I found so far is to unfold the operation into several steps, but the deeper the structure the uglier this gets.
clc; clear variables;
% Dummy data
my_struc.points(1).fieldA = 100;
my_struc.points(2).fieldA = 200;
my_struc.points(3).fieldA = 300;
my_struc.points(1).fieldB.subfieldM = 10;
my_struc.points(2).fieldB.subfieldM = 20;
my_struc.points(3).fieldB.subfieldM = 30;
my_struc.points(1).fieldC.subfieldN.subsubfieldZ = 1;
my_struc.points(2).fieldC.subfieldN.subsubfieldZ = 2;
my_struc.points(3).fieldC.subfieldN.subsubfieldZ = 3;
my_struc.info = 'Note my_struc has other fields besides "points"';
% Get all fieldA values by just indexing (this works):
all_fieldA_values = [my_struc.points(:).fieldA]
% Get all subfieldM values by just indexing (doesn't work):
% all_subfieldM_values = [my_struc.points(:).fieldB.subfieldM]
% Ugly workaround:
temp_array_of_structs = [my_struc.points(:).fieldB];
all_subfieldM_values = [temp_array_of_structs.subfieldM]
% Get all subsubfieldZ values by just indexing (doesn't work):
% all_subsubfieldZ_values = [my_struc.points(:).fieldC.subfieldN.subsubfieldZ]
% Ugly workaround:
temp_array_of_structs1 = [my_struc.points(:).fieldC];
temp_array_of_structs2 = [temp_array_of_structs1.subfieldN];
all_subsubfieldZ_values = [temp_array_of_structs2.subsubfieldZ]
Output:
all_fieldA_values =
100 200 300
all_subfieldM_values =
10 20 30
all_subsubfieldZ_values =
1 2 3
Thanks for any help!

Akzeptierte Antwort

Jorge
Jorge am 12 Aug. 2019
Thanks for the answers & comments; turns out it's possible to use arrayfun() to this purpose!:
all_subfieldM_values = arrayfun(@(in) in.fieldB.subfieldM, my_struc.points)
all_subsubfieldZ_values = arrayfun(@(in) in.fieldC.subfieldN.subsubfieldZ, my_struc.points)
This achieves the desired effect with a single line of code :)

Weitere Antworten (1)

TADA
TADA am 11 Aug. 2019
As always, you can use a small utility function to drill down the object hierarchy
It's probably not the most elegant solution because you have to write the field names as strings, so don't expect any intellisence there, but hey, subsref does the same thing so...
function b = drillref(a, s)
fields = strsplit(s, '.');
b = a;
for i = 1:numel(fields)
b = [b.(fields{i})];
end
end
A = drillref(my_struc, 'points.fieldA')
A =
100 200 300
B_M = drillref(my_struc, 'points.fieldB.subfieldM')
B_M =
10 20 30
C_N_Z = drillref(my_struc, 'points.fieldC.subfieldN.subsubfieldZ')
C_N_Z =
1 2 3

Kategorien

Mehr zu Structures finden Sie in Help Center und File Exchange

Produkte


Version

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by