Search code examples
matlabfor-loopfieldmatlab-struct

MATLAB: Storing values in a structure


Good day MATLAB pros,

I have a long list of (single value) variables in my workspace that has to be stored into an array for every loop of execution.

Here's a simple example: Variables in the workspace:

a = 1;
b = 2.2;
c = 3.4;
d = [0.5 0.7 1 1.2 1.5];
e = [-15 -10 -5 0 5 10 15 20];
serial = {'WTZ00151'};
model = {'336F'};

NameList = {'a';'serial';'model'};

1) Here, I'm saving only the single value variables into Data structure, however what I'd like to do is for every loop, save the single values into an array in Data structure.

varList = who;
Data = struct;

fields = fieldnames(Data, '-full');
fieldSizes = structfun(@(field) length(field),Data);

% removing arrays from structure
for lst = 1:length(fieldSizes)
    if fieldSizes(lst) > 1
        Data = rmfield(Data,fields(lst));
    end
end

Data = 

      Data: [1x1 struct]
         a: 1
         b: 2.2000
         c: 3.4000
     index: 10
     model: {'336F'}
    serial: {'WTZ00151'}

So if I run this in a loop, for i = 1:5, Data should look like this:

Data = 

      Data: [1x1 struct]
         a: [1 1 1 1 1]
         b: [1x5 double]
         c: [1x5 double]
     index: [10 10 10 10 10]
     model: {1x5 cell}
    serial: {1x5 cell}

Any ideas on how to code the for loop?

2) Since there are too many variables in the workspace & I have a long list of variables that needs storing, instead of using who to save ALL variables to the structure (and then filtering out the unwanted), how could I use a list of variable names (imported from a text file: NameList) to call out what needs to be stored? Using the variable name from NameList does not call out the structure values.

Much appreciated,


Solution

  • It's not immediately clear what part of your code actually is creating your data structure. There are several ways to create a struct from your array of variable names.

    One way is to save the relevant variables to a file and load them back into a struct

    save('tmp.mat', NameList{:});
    Data = load('tmp.mat');
    

    Another option (not recommended) is to use eval

    for k = 1:numel(NameList)
        Data.(NameList{k}) = eval(NameList{k});
    end
    

    As far as storing data from multiple iterations, I personally would recommend storing the data into an array of struct rather than a struct of arrays. You should be able to store each Data instance in an array using k as an index as shown below:

    allData(k) = Data;
    

    If you decide you really want a struct of arrays, you can always convert it afterwards.

    fields = fieldnames(allData);
    
    output = struct();
    
    for k = 1:numel(fields)
        % Try to just concatenate the values together
        try
            values = [allData.(fields{k})];
    
        % If that failed, concatenate them within a cell array
        catch
            values = {allData.(fields{k})};
        end
    
        % Store this in a single output struct
        output.(fields{k}) = values;
    end