Dynamically Assign Variables in Matlab

我是研究僧i 提交于 2019-11-27 08:15:30

问题


I have the following function as part of a large codebase, which I inherited:

function = save_function(fpath, a,b,c)
    save(fpath, 'a', 'b', 'c')
end

This function is called at the end of one script, before another script is to be executed. This way, the variable names are properly saved (bad design, I know - I didn't write this code).

Now, I am making changes to the codebase, and realize that I need to store more variables in fpath. I face two options:

  1. Edit save_function to accept more inputs. This would break any other code in the codebase that also uses this function
  2. Write a save_function2(a, b, c, d, e, ...) that I will call in the code that I change. This seems like bad design as well.

What I would ideally like to do, is to allow save_function to take in any number of arguments at a time, and save them all by the variable names that are passed in.

Having done some googling, I found eval and eval_in, which evaluate strings as matlab code. However, there are two problems with using this:

  1. Using eval is horribly slow and quite dangerous
  2. I don't always know the types of my variables beforehand, so I can't create an elegant, generic to_string function

In order to combat the flexible number of variables, I decided to use varargin and inputname as follows:

function = save_function(fpath, varargin)
    names = {}
    for i=1:size(varargin,1)
        names{i} = inputname(i+1);  % have to offset by 1 to account for fpath
    end
    save(fpath, names{:});
end

Unfortunately, since the input variables are held in varargin, they do not exist as their variable names on the stack, so the save line fails

How can I dynamically create these variables on the stack, with their variable names?


回答1:


You can use a structure to dynamically define saved variable names.
This option is documented here.

 function save_function( fpath, varargin )     
 for ii = 1:numel( varargin )
     st.( inputname(ii+1) ) = varargin{ii};
 end
 save( fpath, '-struct', 'st' );

As a rule of thumb, structure with dynamic field names is often better than eval or assignin when it comes to dynamic variable names.

PS,
It is best not to use i as variable name in Matlab.




回答2:


The trick is to use assignin, which takes a workspace, a variable name, and some data. It then creates, in the specified workspace, a variable with the given name, whose value is the data:

assignin(workspace, varname, value)

The workspace identifier can be either 'caller' or 'base'. The former creates the variable in the workspace of the function that called the function within which assignin is called; while the latter... I don't know - it doesn't seem to put the variable anywhere I can see.

The trick is to create a small function to assign variables to the calling workspace, and call this function from within assignin:

function = save_function(fpath, varargin)
    names = {}
    for i=1:size(varargin,1)
        names{i} = inputname(i+1);  % have to offset by 1 to account for fpath
    end
    create_variables(names, varargin);
    save(fpath, names{:});
end

function = create_variables(names, vals)
    for i=1:size(names, 1)
        assignin('caller', names{i}, vals{i});
    end
end


来源:https://stackoverflow.com/questions/24502069/dynamically-assign-variables-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!