MATLAB Answers

Extracting fields from structures with varying names.

57 views (last 30 days)
Karl M
Karl M on 12 Apr 2016
Commented: Karl M on 18 Apr 2016
Hi I have several structures on my workspace. Their names are unrelated (e.g. "data_23_200_600_451", "data_58_588_154_289" etc.), but they all have identical field names. The tricky names of the structures make it difficult to extract the the same field in all structures using a loop (i.e. the names are not 'data_1', 'data_2' etc.) Is there any other method to automatically extract the fields from these structures? Thank you!

  4 Comments

Show 1 older comment
Karl M
Karl M on 12 Apr 2016
Thank you, Guillaume. You are right, the structure names were indeed created using 'eval'. I did not know how to do it otherwise. If the structures were created without resorting to metadata names it would be difficult to keep a track on them. These names are now fait accompli, so I will be pleased if some solution could be suggested. /Karl
Guillaume
Guillaume on 13 Apr 2016
The question is then: how do you want to identify which variables you want to iterate over? Are you planning to provide them as a list of variable names? Or should they be identified automatically because they are structures with the correct fields? Or ...?
Stephen Cobeldick
Stephen Cobeldick on 13 Apr 2016
"The tricky names of the structures make it difficult to extract the the same field in all structures using a loop"
Yes it will be tricky, because the bad program design makes it tricky. Bad program design makes for buggy, inefficient programs. And putting meta data into variable names is one of the slowest and buggiest ideas that beginners keep dreaming up. Any "solution" to "loop over" those variables is going to be a slow, pointless, buggy workaround for a poor design decision:
"If the structures were created without resorting to metadata names it would be difficult to keep a track on them" It is much easier to put the meta data in fields of the structure: faster, easier, and trivial to access.

Sign in to comment.

Accepted Answer

Fangjun Jiang
Fangjun Jiang on 12 Apr 2016
Use this example to see if it helps to resolve your issue
clear;
data_23_200_600_451=struct('strings',{{'hello','yes'}},'lengths',[5 3]);
data_58_588_154_289=struct('strings',{{'abc','efg'}},'lengths',[5 3]);
save;
Vars=load;
StructNames=fieldnames(Vars);
for k=1:numel(StructNames)
Vars.(StructNames{k}).strings
end

  2 Comments

Karl M
Karl M on 13 Apr 2016
Thank you, Fangjun Jiang! This is exactly what I needed!
Guillaume
Guillaume on 13 Apr 2016
If this solve your problem, it's the most convoluted and slowest way of solving it. Saving the workspace to a file and reading it again is a complete waste of time.
You haven't answered my latest comment, but if this work, does this mean that all the variables in the workspace are structures you want to iterate over?

Sign in to comment.

More Answers (2)


Guillaume
Guillaume on 13 Apr 2016
As per my comment to the accepted answer, save and load is the most inefficient way of solving your problem (and could fail if you don't have write access to the current directory). If all the variables in the workspace are all structures you want to access, then using who is the fastest way:
"If the structures were created without resorting to metadata names it would be difficult to keep a track on them". No, there are many ways of keeping track of variables without using eval and without embedding metadata in the variable name: tables, structures, maps, etc. It would have been better for you to ask how to do that first rather than asking how to solve the mess you've created.
Anyway, this will be faster than save and load and will clean up the mess a bit:
varnames = who; %query the name of all workspace variables
%now clean up a bit by putting them all in a structure:
data = struct();
for varname = varnames'
data.(varname{1}) = eval(varname);
clear(varname);
end
%all your orignal structures are now fields of data.
%to iterate over them:
for varname = fieldnames(data)'
x = data.(varname{1}).somecommonfield;
end

  3 Comments

Fangjun Jiang
Fangjun Jiang on 13 Apr 2016
Guillaume, I don't know exactly what is the user's issue. I just sense that the difficulty is to programly access the irregular name of the structure data. Using load() with a return argument is a good way to achieve it. who() command only gives the name. You still need to use eval() to copy the data into a structure. That may not be more efficient.
Most likely, I would guess that the user already has those similar structure data saved in a .mat file. In that case, use load() is the most easy and efficient way to resolve the issue.
Guillaume
Guillaume on 14 Apr 2016
Writing data to disk to just read it again is going to orders of magnitude slower than reading it straight from memory.
If the data is already save in a .mat file, then we're going back to my initial comment to the question. It's better not to create those variables in the first place, and indeed load with a return argument is one way to solve this. However, the OP has indicated that these variables were created with eval.
Karl M
Karl M on 18 Apr 2016
Thank you, Guillaume for your comments. I do agree that there should have been better ways to to design my algorithm without resorting to the apparently infamous 'eval'. To answer your initial question, yes, all the variables to iterate over are structures. Saving the structures once again in the 'matlab.mat' file and then loading them anew does sound indeed as extra work, but since my data are not big, it is not an issue here.

Sign in to comment.

Sign in to answer this question.