Home How to return the leaves of a struct as vector in Matlab?

How to return the leaves of a struct as vector in Matlab?

Jonas Stein
1#
Jonas Stein Published in 2017-10-30 17:58:21Z
 Often I need to access the leaves of data in a structured array for calculations. How is this best done in Matlab 2017b? % Minimal working example: egg(1).weight = 30; egg(2).weight = 33; egg(3).weight = 34; someeggs = mean([egg.weight]) % works fine apple(1).properties.weight = 300; apple(2).properties.weight = 330; apple(3).properties.weight = 340; someapples = mean([apple.properties.weight]) %fails weights = [apple.properties.weight] %fails too % Expected one output from a curly brace or dot indexing expression, % but there were 3 results. 
gnovice
2#
 If only the top level is a non-scalar structure array, and every entry below is a scalar structure, you can collect the leaves with a call to arrayfun, then do your calculation on the returned vector: >> weights = arrayfun(@(s) s.properties.weight, apple) % To get the vector weights = 300 330 340 >> someapples = mean(arrayfun(@(s) s.properties.weight, apple)) someapples = 323.3333  The reason [apple.properties.weight] fails is because dot indexing returns a comma-separated list of structures for apple.properties. You would need to collect this list into a new structure array, then apply dot indexing to that for the next field weight.
 You can collect properties into a temporary structure array, and then use it as normal: apple_properties = [apple.properties]; someapples = mean([apple_properties.weight]) %works  This wouldn't work if you had even more nested levels. Perhaps something like this: apple(1).properties.imperial.weight = 10; apple(2).properties.imperial.weight = 15; apple(3).properties.imperial.weight = 18; apple(1).properties.metric.weight = 4; apple(2).properties.metric.weight = 7; apple(3).properties.metric.weight = 8;  Not that I would advise such a structure, but it works as a toy example. In that case you could, do the same as the previous in two steps... or you could use arrayfun. weights = arrayfun(@(x) x.properties.metric.weight, apple); mean(weights)