Accessing field data in nonscalar structure array

3 vues (au cours des 30 derniers jours)
KAE
KAE le 18 Nov 2019
Commenté : KAE le 19 Nov 2019
Let's say I have a nested non-scalar structure array,
Patient(1).Vitals.weight = 185;
Patient(1).Vitals.temperature = [98 96 100 101];
Patient(1).Vitals.mood = {'Good'};
Patient(1).Location.state = 'VA';
Patient(2).Vitals.weight = 203;
Patient(2).Vitals.temperature = [97 97 98 99];
Patient(2).Vitals.mood = {'Fair'};
Patient(2).Location.state = 'NC';
Patient(3).Vitals.weight = 190;
Patient(3).Vitals.temperature = [98 99 99 100];
Patient(3).Vitals.mood = {'Bad'};
Patient(3).Location.state = 'CT';
I would like to acess the data, for example creating (a) a vector containing the weights [185 203 190], (b) a cell array containing the states {'VA', 'NC', 'CT'}, and (c) a matrix containing the temperature values [98 96 100 100; 97 97 98 99; 98 99 99 100]. I want to avoid looping through Patient(1), Patient(2), etc. since my real structure array is large. How do I extract the data? Some failed attempts are listed below.
Patient.Vitals.weight
% Expected one output from a curly brace or dot indexing expression, but there were 2 results.
[Patient.Vitals.weight]
% Expected one output from a curly brace or dot indexing expression, but there were 2 results.
Patient(:).Vitals.weight
% Expected one output from a curly brace or dot indexing expression, but there were 2 results.
Any suggestions? Or is there some other data storage form better suited to data extraction? [I am using multilevel nesting because my real structure is an output of xml2struct, and perhaps I could flatten the results, but then I will lose some data organization.]

Réponse acceptée

Daniel M
Daniel M le 18 Nov 2019
Modifié(e) : Daniel M le 18 Nov 2019
Here is a solution. You'll have to write the functions differently for gathering cells and arrays.
fun = @(s,field) {s.(field)}; % use {} for string/char
output = fun([Patient.Location],'state');
% ans = 1×3 cell array
% {'VA'} {'NC'} {'CT'}
fun2 = @(s,field) [s.(field)]; % use [] for numbers
output = fun2([Patient.Vitals],'weight');
% ans = 185 203 190
And this even works in R2019b:
f1 = @(s,field) [s.(field)];
f2 = @(s,field,subfield) [f1(s,field).(subfield)];
output = f2(Patient,'Vitals','weight');
% ans = 185 203 190
But this essentially does the same thing as creating a temporary struct, [Patient.Vitals], and then indexing into that. It can just be neatly arranged into an anonymous function.
There is probably also a way to do this with subsref, but it would probably get complex.
  5 commentaires
Guillaume
Guillaume le 19 Nov 2019
If your xml schema chan be flattened into one or more table, I would consider using that. But indeed, matlab hasn't got an efficient way of storing xml (or json) data. You could use containers.Map but its implementation in matlab leaves a lot to be desired.
KAE
KAE le 19 Nov 2019
Thanks. Perhaps there is a solution outside Matlab that I can call from within Matlab to access XML data. I will look around.

Connectez-vous pour commenter.

Plus de réponses (1)

Guillaume
Guillaume le 18 Nov 2019
This is one of the reason I dislike multilevel structures (the other being they're very inefficient memory-wise), there's no easy way to extract all the data from the leaves at once.
The best you can do is probably:
tempvitals = vertcat(Patient.Vitals); %concatenate all the Vitals fields. Note that they must all have the same fields themselves
Weight = vertcat(tempvitals.weight);

Catégories

En savoir plus sur Structures dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by