【问题标题】:Dynamically Assign Variables in Matlab在 Matlab 中动态分配变量
【发布时间】:2014-07-01 03:28:54
【问题描述】:

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

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 一次接收任意数量的参数,并通过传入的变量名将它们全部保存。

在谷歌搜索后,我找到了evaleval_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行失败

如何在堆栈上动态创建这些变量及其变量名?

【问题讨论】:

  • 我迟到了6年,但你好像想直接打电话给save

标签: matlab dynamic-variables


【解决方案1】:

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

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

根据经验,structure with dynamic field names 在动态变量名称方面通常优于evalassignin

PS,
最好是not to use i as variable name in Matlab

【讨论】:

  • 更改save_function 来保存结构是不可取的,因为大型代码库的其他部分希望它自己保存变量。
  • @inspectorG4dget 仔细阅读有关保存中'-struct' 标志的手册:它不保存结构,而是将结构字段保存为单独的变量,这正是您想要的。
【解决方案2】:

诀窍是使用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-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-29
    • 2012-11-08
    • 1970-01-01
    • 2014-07-12
    • 2011-01-11
    相关资源
    最近更新 更多