【问题标题】:Sharing "many" variables between functions in Matlab在 Matlab 中的函数之间共享“许多”变量
【发布时间】:2016-04-29 22:25:00
【问题描述】:

在 Matlab 中,我有几条数据库记录存储在矩阵 DataMatrix 中。矩阵的每一行是一条记录,每一列是记录的一个属性的值。 为了使程序易于理解DataMatrix 的每一列,我定义了一个变量名来解释与该列关联的属性,即:

ColApple = 1;
ColOrange = 2;
ColLemon = 3;
...

我有大约50 列要命名。

我的问题是DataMatrix 中的值用于不同的函数,我希望始终使用列名来处理DataMatrix 中的数据。所以我必须在不同的函数之间共享ColAppleColOrangeColLemon...的值

到目前为止,我想到了两种可能的方法:

  1. 使列名全局化

  2. 定义一个返回列名值的函数,即:

    [ColApple, ColOrange, ColLemon, ... ] = getColNames

我会避免使用全局解决方案,因为我认为它很危险,而且如果可能的话,我希望列名保持不变。 第二种方法更好,但由于我有 50 列,我不知道让函数返回 50 不同值是否是个好主意(在我看来也很难维护)。

谁有更强大或可维护的方法来解决这个问题?我确定我不是第一个处理此问题的人,但我无法找到解决方案。

【问题讨论】:

    标签: matlab parameter-passing


    【解决方案1】:

    不要使用全局变量,因为它们容易出错。创建 50 个变量名也不是很防错(参见:dynamic variable naming)。

    在这种情况下,我会选择一个简单的cell array。您可以从数据矩阵的第一行读取名称(如果它们写在那里),或者如果您现在正在这样做,则可以手写它们。

    ColumnNames = {'Col1', 'Col2', 'Col3', (...) , 'Col 50'}
    

    这将为您提供一个 1 x 50 单元格数组,其中包含您的列名。只需输入正确的列号即可找到名称,即第 22 列将是 ColumnNames{1,22}。您现在可以将变量 ColumnNames 作为单个变量传递给其他函数。如果您不使用动态变量命名,则为了获取相应的列名,但是例如你的colApple,你可以使用strcmp

    ColIdx = find(strcmp(ColumnNames,'colApple'));
    

    这样strcmp 会检查哪个单元格包含字符串'colApple',而find 返回所请求单元格的索引号。

    我在自己的代码中传递了很多变量,我在 structure array 中这样做,因为它能够存储各种不同的数据,并且每个结构条目都有一个合理的名称:

    result.data = [m x 9 double]
    result.grid.z = ~[5000 x 5500 double]
    result.filename = 'filename.asc'
    ...
    

    【讨论】:

    • 谢谢,但我不确定我是否完全理解答案。使用您的示例 ColumnNames{1,22} 返回 Col 22 因此,给定列号,我得到列名。给定function1function2 这两个函数,我将变量ColumnNames 传递给它们我确信,给定相同的列号,我得到相同的列名。但我正在寻找的是相反的:给定相同的列名,我希望拥有相同的列号。这样命令DataMatrix(:, Col22) = something 将在function1function2 中的同一列上工作
    • 也许你认为在通过ColumnNames 之后我应该使用for ii = 1: length(ColumnNames) str = [ColumnNames{1,ii} ' = ' int2str(ii)]; eval(str); end 之类的东西来创建变量
    • @MeSS83 我从来不认为使用eval 是一个好主意,从来没有。请参阅有关使用动态变量名称的链接帖子。 eval 破坏了与 MATLAB 相关的所有内容,我认为不适合使用。如果您不移动数据中的列,那么如果您将数据从一个函数传递到另一个函数,第 22 列仍将是第 22 列,所以我看不出那里有问题。
    • 你是完全正确的第 22 列在我的情况下始终是第 22 列,但在我的代码中我没有写 DataMatrix(:, 22) = something 而是我有 DataMatrix(:, ColLemon) = something。我这样做是因为我认为它更具可读性,并且因为将来ColLemon 的值可能会改变。所以我会确保在我的程序ColLemon 的每个函数中都具有相同的值。我根本不明白如何使用你的解决方案,通过ColumnNames,来实现这个
    • @MeSS83 没错。我不知道容器地图,所以我在那里破解了我的方式。不过,我确实敦促您通读我关于动态变量命名的链接答案,以防止您使用 eval 及其所有相关的陷阱和故障。
    【解决方案2】:

    这非常适合container maps。容器映射允许创建字典。例如

    fruits = containers.Map({'Apple', 'Orange', 'Lemon'}, [1, 2, 3])
    

    将创建字典

    'Apple'   ->   1
    'Orange'  ->   2
    'Lemon'   ->   3
    

    您可以使用

    找到所需的列号
    >> fruits('Orange')
    
    ans =
    
         2
    

    【讨论】:

    • 在这里我想我有一个很好的解决方案;)总是有人有一个内置的,它完全符合要求。干得好!
    • @hbaderts 这正是我想要的,谢谢
    猜你喜欢
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 2017-03-27
    • 2016-03-25
    • 2017-11-19
    • 1970-01-01
    相关资源
    最近更新 更多