0

I have several files "2011-01-01.txt", "2013-01-02.txt", "2015-02-01.txt", etc. I wish to create a struct variable for each of the file such that (the values are made up):

machine20110101.size=[1,2,3];
machine20110101.weight=2345;
machine20110101.price=3456;

machine20130102.size=[2,3,4];
machine20130102.weight=1357;
machine20130102.price=123;

machine20150201.size=[1,2,4];
machine20150201.weight=1357;
machine20150201.price=123;

And,

save('f20110101.mat','machine20110101');
save('f20130102.mat','machine20130102') ;
save('f20150201.mat','machine20150201');

As we can see, the struct names are derived from the files' names. How can I construct the above struct variables?

I've searched for a while, but I didn't figure out how to use genvarname.

And these links (dynamic variable names in matlab, dynamic variable declaration function matlab, Dynamically change variable name inside a loop in MATLAB) didn't solve my problem.

I'm using MATLAB R2012b, so functions like matlab.lang.makeUniqueStrings defined after this version is unavailable.

Community
  • 1
  • 1
user3813057
  • 891
  • 3
  • 13
  • 31
  • 5
    The literal answer to the question involves [`eval`](http://www.mathworks.com/help/matlab/ref/eval.html), which I would strongly recommend against doing. Instead, prune the dashes out of the filename (obtained using [`fileparts`](http://www.mathworks.com/help/matlab/ref/fileparts.html)) using [`strrep`](http://www.mathworks.com/help/matlab/ref/strrep.html) or [`regexprep`](http://www.mathworks.com/help/matlab/ref/regexprep.html) to [use as a fieldname](http://www.mathworks.com/help/matlab/matlab_prog/generate-field-names-from-variables.html) for a nested structure (e.g. mydata.machine20110101) – sco1 Jul 07 '15 at 00:46
  • exactly, using `fileparts` and `strrep` is much better than `genvarname`, which according to Matlab will be removed soon... – scmg Jul 07 '15 at 02:13
  • 1
    It is possible if you use the tricks in the above comments. However, this is a design I would recommend against. The next problem you will face here is that you, in the rest of the code, will not know the name of the variable. You will have to adapt the code to handle this magic. It may also make the code hard to read for the people coming after. The more common solution to this problem is to add a field `name` or `tag`. You can keep the variable name machine, and use a name like `'20110101'` or `machine20110101`. Note that this must be handled when reading the file to avoid overwriting. – patrik Jul 07 '15 at 05:45

2 Answers2

0

Now that I'm in front of MATLAB, here's an example based on my comment above, utilizing dynamic field names with the filenames pruned using fileparts and regexprep in a cellfun call.

% Sample list for testing here, use uigetdir with dir or whatever method to
% get a list of files generically
filelist = {'C:\mydata\2011-01-01.txt', ...
                'C:\mydata\2012-02-02.txt', ...
                'C:\mydata\2013-03-03.txt', ...
                'C:\mydata\2014-04-04.txt', ...
                };
nfiles = length(filelist);

% Get filenames from your list of files
[~, filenames] = cellfun(@fileparts, filelist, 'UniformOutput', false);

% Prune unwanted characters from each filename and concatenate with 'machine'
prunedfilenames = regexprep(filenames, '-', '');
myfieldnames = strcat('machine', prunedfilenames);

% Generate your structure
for ii = 1:nfiles
    % Parse your files for the data, using dummy variables since I don't 
    % know how your data is structured
    loadedsize = [1, 2, 3];
    loadedweight = 1234;
    loadedprice = 1234;

    % Add data to struct array
    mydata.(myfieldnames{ii}).size = loadedsize;
    mydata.(myfieldnames{ii}).weight = loadedweight;
    mydata.(myfieldnames{ii}).price = loadedprice;
end

@patrik raises some good points in the comments. I think the more generic method he would like to see (please correct me if I'm wrong) goes something like this:

% Sample list for testing here, use uigetdir with dir or whatever method to
% get a list of files generically
filelist = {'C:\mydata\2011-01-01.txt', ...
                'C:\mydata\2012-02-02.txt', ...
                'C:\mydata\2013-03-03.txt', ...
                'C:\mydata\2014-04-04.txt', ...
                };
nfiles = length(filelist);

% Get filenames from your list of files
[~, filenames] = cellfun(@fileparts, filelist, 'UniformOutput', false);

% Prune unwanted characters from each filename and concatenate with 'machine'
prunedfilenames = regexprep(filenames, '-', '');
mytags = strcat('machine', prunedfilenames);

% Preallocate your structure
mydata = repmat(struct('tag', '', 'size', [1, 1, 1], 'weight', 1, 'price', 1), nfiles, 1);

% Fill your structure
for ii = 1:nfiles
    % Parse your files for the data, using dummy variables since I don't 
    % know how your data is structured
    loadedsize = [1, 2, 3];
    loadedweight = 1234;
    loadedprice = 1234;

    % Add data to struct array
    mydata(ii).tag = mytags{ii};
    mydata(ii).size = loadedsize;
    mydata(ii).weight = loadedweight;
    mydata(ii).price = loadedprice;
end
sco1
  • 12,154
  • 5
  • 26
  • 48
0

Besides @excaza's answer, I used the following approach:

machine.size = [1,2,3]; machine.price = 335; machine.weight = 234;

machineName = ['machine',the_date];

machineSet = struct(machineName,machine);

save(OutputFile,'-struct','machineSet',machineName);

user3813057
  • 891
  • 3
  • 13
  • 31