2

作为我继承的大型代码库的一部分,我具有以下功能:

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

这个函数在一个脚本结束时调用,在另一个脚本被执行之前。这样,变量名就被正确保存了(我知道设计不好——我没有写这段代码)。

现在,我正在对代码库进行更改,并意识到我需要在fpath. 我面临两个选择:

  1. 编辑save_function以接受更多输入。这将破坏代码库中也使用此函数的任何其他代码
  2. 写一个save_function2(a, b, c, d, e, ...)我将在我更改的代码中调用的代码。这似乎也是糟糕的设计。

我最理想的做法是允许save_function一次接收任意数量的参数,并通过传入的变量名将它们全部保存。

在进行了一些谷歌搜索后,我发现evalandeval_in将字符串评估为 matlab 代码。但是,使用它有两个问题:

  1. 使用eval速度非常慢而且非常危险
  2. 我并不总是事先知道我的变量的类型,所以我无法创建一个优雅的通用to_string函数

为了打击灵活数量的变量,我决定使用varargininputname如下:

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

不幸的是,由于输入变量保存在 中varargin,因此它们在堆栈中不作为变量名存在,因此该save行失败

如何使用它们的变量名在堆栈上动态创建这些变量?

4

2 回答 2

2

您可以使用结构来动态定义保存的变量名称。此处
记录了此选项。

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

根据经验,具有动态字段名称的结构eval通常比assignin动态变量名称更好。

PS,
最好不要i在 Matlab 中用作变量名

于 2014-07-01T06:34:44.560 回答
0

诀窍是使用assignin,它需要一个工作区、一个变量名和一些数据。然后它在指定的工作空间中创建一个具有给定名称的变量,其值为数据:

assignin(workspace, varname, value)

工作区标识符可以是'caller''base'。前者在调用被调用函数的函数的工作区中创建变量assignin;而后者......我不知道 - 它似乎没有将变量放在我能看到的任何地方。

诀窍是创建一个小函数来将变量分配给调用工作区,并从内部调用此函数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
于 2014-07-01T03:28:54.837 回答