dontpanic
dontpanic

Reputation: 153

Create array of "deep" struct (scalar) fields

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!

Upvotes: 2

Views: 54

Answers (1)

rinkert
rinkert

Reputation: 6863

You can use arrayfun to have acces to each individual 'point', and then acces its data. This will return an array with the same dimensions as my_struc.points:

all_subfieldM_values = arrayfun(@(in) in.fieldB.subfieldM, my_struc.points)
all_subsubfieldZ_values = arrayfun(@(in) in.fieldC.subfieldN.subsubfieldZ, my_struc.points)

Not optimal, but at least it's one line.

Upvotes: 1

Related Questions