Create a structure name based on the string of a variable. Create fieldnames in this structure.

712 views (last 30 days)
Inside a function I have a variable called name which is a char class. I want to generate a structure based on the string of variable *name *and then create fields in this structure.
name =
report 1
I do the following to create a variable with the string of variable name.
v=genvarname(strrep(name, ' ', '_'));
Then in my function I have created other variables which have certain values. I want to create fieldnames in the previous structure with the name of these variables. Those fieldnames will have the same value as the corresponding value of the variable.
a=mean([1 2 3 4]);
b=std([1 2 3 4]);
What I want to create is the following:
report_1.a= 2.5000
My final goal is to create an output in the function with structure report_1.

Accepted Answer

Stephen23 on 1 Sep 2015
Edited: Stephen23 on 1 Sep 2015
The simplest answer would be to use a non-scalar structure, which is exactly intended for this kind of data collection:
>> data(3).A = pi;
>> data(2).A = 0;
>> data(1).A = -Inf
>> data(3).B = 8;
>> data(2).B = 4;
>> data(1).B = 2;
>> mean([data.B])
ans =
>> data(1).A
ans =

More Answers (5)

Cedric Wannaz
Cedric Wannaz on 17 Jun 2013
Edited: Cedric Wannaz on 17 Jun 2013
Why do you want to do this? In my experience, cases where it is appropriate to define dynamically variables names are extremely rare. Dynamical field name generation is more frequent though.
In any case, your function's output arguments will be copied into variables that are define outside of the function, so there is no point in defining a structure name dynamically within the function. To illustrate..
function outStruct = myFunction(values, fieldNames)
outStruct.(fieldNames{1}) = sum(values) ;
outStruct.(fieldNames{2}) = mean(values) ;
.. and a call from elsewhere (command line, script, etc):
S = myFunction([5, 6, 7], {'a', 'b'}) ;
This leads to S being a struct with two fields: a = 18, and b = 6.
As you can see S is not known as a local variable within myFunction, but what will ultimately be S value is built under the local variable name outStruct within the function. So you see that if you wanted to generate a name for S dynamically, it would have to be done outside of the function. You also see how to define field names dynamically: myStruct.(fieldname1) = value1, etc.
But again, dynamically building variable names is rarely legitimate. If you wanted, for example, to read multiple files which include field names and values, and have their content stored in structs with these field names, you could create a cell array of structs indexed by a file ID if field names could vary among files, or a struct array if fields would be similar among files.
Cedric Wannaz
Cedric Wannaz on 18 Jun 2013
One could list a variety of reasons not to create dynamically variables/names; I will just mention a practical one: as long as you are working "by hand" in the workspace, having these variables is fine, but if you wanted to use this approach in a more automated structure, you would have a "hard" time accessing the variables in the base workspace/stack from any function for example, and it would not be that easy to pass them to functions during function calls.
Have you thought about grouping all these variables under an overarching struct? To illustrate
Content = struct() ;
for k = 1 : nFolders
folderName = ... % E.g. 'Data 1'
folderFieldName = ... % E.g. 'Data_1'
Content.(folderFieldName) = readFolder( folderName, ... ) ;
Using your example above, you would have
which you could easily browse, pass as a whole or by block to a function, etc. Getting field names in an automated mechanism would also be easier to implement than accessing variables from the base stack.

Sign in to comment.

Tom on 17 Jun 2013
You can make a function to process the names into a structure:
function out = Var_Names(varargin)
for n = 1:nargin
out.(inputname(n)) = varargin{n};
Then run:
a=mean([1 2 3 4]);
b=std([1 2 3 4]);
s = Var_Names(a,b);
To give the structure its required variable name, you can run
name = 'report 1';
eval([genvarname(name),' = s'])
As everyone will tell you, it's not good to use the EVAL function, so instead it might be better to add a field to the structure with the name, e.g.
s.StructName = genvarname(name);

Andrei Bobrov
Andrei Bobrov on 17 Jun 2013
report_1 = cell2struct(num2cell([mean(1:4) std(1:4)]),{'a','b'},2);
  1 Comment
Giorgos Papakonstantinou
Giorgos Papakonstantinou on 17 Jun 2013
But I don't know know before hand the string of name. In this case is
report 1
What happens when it the variable name is
report 2
So I want the name of the structure to change dynamically.

Sign in to comment.

Hi Giorgos I have a similar problem. I read data from excel where the column names are stored like Speed_55m.max Speed_55m.min Speed_55m.stdev Speed_55m.value. That repeats for different heights. I use [a,b]=xlsread('IEA_Task32_Dataset_PP_RR.xlsx'); and then I would like to use a for loop to create structures
Something like that for icol=1:size(a,2) char(b{icol})=a(:,icol); end
my target is for different height to create a structure where I have data for max, min and std

msand65 on 10 Nov 2017
Edited: msand65 on 10 Nov 2017
I wrote a simple function many years ago ("remove_bad_chars.m") that replaces the characters not allowed in a structure name (using strrep and regexprep mostly) with acceptable characters for a structure name. There is a little more to it than that (can't start with a number or _, replace _ _ with _ etc) but it is a simple function that I have been adding to through time as I run into a new character that a structure name can't contain or header names that are more complex.
For example, say I read in a CSV file and the first row of that file contains the column names. Suppose one header is 'temp (K)', this function changes it to 'temp_K'. Then I can implore the use of dynamic structures to assign the column of data to a structure with that fieldname, say data.temp_K.
Guillaume on 10 Nov 2017
Note that if you use makeUniqueStrings after makeValidName, you have to be careful that makeUniqueStrings does not generate names that are too long and thus invalid variable names. Even Mathworks got that workflow wrong in the implementation of matlab.internal.json.makeStructure in R2017a (fixed in R2017b).
%some invalid variable names
v = {[repelem('a', 70), 'a']; [repelem('a', 70), 'b']}
%will generate invalid variable names:
newv = matlab.lang.makeUniqueStrings(matlab.lang.makeValidName(v))
%proper usage:
newv = matlab.lang.makeUniqueStrings(matlab.lang.makeValidName(v), 1:numel(v), namelengthmax)

Sign in to comment.


Community Treasure Hunt

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

Start Hunting!