【问题标题】:Matlab: Can I refer to array indices via unique names?Matlab:我可以通过唯一名称引用数组索引吗?
【发布时间】:2012-05-01 04:00:28
【问题描述】:

假设我有一个列矩阵pols,其中包含 [theta, rho, z] 的向量。 这意味着,如果我有 9 个这样的向量,它将是一个 9x3 矩阵。 像这样安排它们非常方便,因为我可以将它们中的任何一个提供给像pol2cart这样的函数:

cart3 = pol2cart(pols(3,:));

对于某个向量,我可以通过索引 1、2、3 找到它的分量:

rho5 = pols(5,2);

但有时矩阵实际上在另一个更宽的矩阵内,并且可能在中间而不是开头,这样上面可能会变成:

rho5 = pols(5,6);

为了使代码在其他人必须维护时更具可读性,是否可以通过唯一名称引用索引?喜欢

rho5 = pols(5).rho;

可以在前面定义 .rho 映射到具有 rho 值的列。

我曾冒险使用mat2cellcell2struct 将矩阵转换为单元格,然后再转换为数组,但这似乎并不实用。或者,我可以创建一个结构数组,但是我失去了执行pol2cart(pols) 的能力,而是必须执行

pol2cart(pols.theta, pols.rho, pols.z);

所以重复这个问题:我可以将索引映射到唯一名称吗?

【问题讨论】:

  • 您的第一行代码不起作用。 POL2CART 需要 2(或 3)个输入参数,而不是单个向量参数。您使用的是哪个版本的 MATLAB?
  • 其实我只在Octave上测试过,因为我没有Matlab,但我必须帮助我正在使用它的朋友。所以如果 pol2cart 不接受这样的论点,那么第一个论点不成立。尽管如此,能够通过名称寻址到索引还是很方便的。

标签: matlab matrix data-structures matlab-struct


【解决方案1】:

没有。你不能这样做。就这么简单。

【讨论】:

    【解决方案2】:

    好的,正式的答案可能是上面木片给出的“否”。但是,如果你真的想做这样的事情,你也许可以使用半破解。具体来说,您可以定义一个类并重载一个运算符来实现(几乎)您想要的。 不幸的是,我看到 Matlab 不允许重载.,所以你必须使用其他一些运算符。(参见下面的编辑)

    只是给你一个想法,这里有一个类,它通过M^i返回矩阵M的第i行。

    classdef Test
      properties
        M;
      end
    
      methods
        function this = Test(M)
          this.M = M;
        end
    
        function res = mpower(this, i)
          res = this.M(i, :);
        end
      end
    end
    

    而且可以这样运行:

    >> tmp = Test([1 2; 3 4]);
    >> tmp^1
    
    ans =
    
         1     2
    
    >> tmp^2
    
    ans =
    
         3     4
    

    使用风险自负! :)

    编辑:

    我错了。正如 gnovice 的回答中提到的,您实际上可以使用方法 subsref 为自定义类定义 . 运算符。

    【讨论】:

    • 哇,这太恶心了!很高兴知道我能做到这一点:) 虽然可能不适合与其他人一起工作(我认为这就是为什么有些人避免运算符重载的原因?)
    【解决方案3】:

    对于默认的 MATLAB 数据类型,不,您不能真正做到这一点。但是,您可以使用create your own new data type (i.e. class object) 来存储您的数据。在类定义中,您将重载subsref 方法来定义下标引用(即使用(){}.)对新对象的行为方式。这在处理对象数组时可能会变得相当棘手,但这是可能的。

    请注意,您还必须为要在新数据类型上使用的所有现有函数创建重载方法。具体来说,您必须为您的对象创建一个 pol2cart 方法,该方法可以在内部调用内置的 pol2cart 函数,并将对象中的适当数据片段作为参数传递。

    ...这为您的当前情况带来了一个更简单的解决方案。您可以创建一个结构数组(或数组的标量结构)来存储您的数据,并简单地为struct data types 创建一个新的重载pol2cart 函数,这将简化调用语法,而不是创建一个全新类型的类对象。

    我在另外两个答案herehere 中讨论了内置数据类型的重载函数的更多细节。简而言之,您将创建一个名为@struct 的文件夹并将其放在您的MATLAB path 上的一个文件夹中。在这个 @struct 文件夹中,您可以放置​​这个重载函数:

    function varargout = pol2cart(polarCoordinates)
      [varargout{1:nargout}] = pol2cart(polarCoordinates.theta, ...
                                        polarCoordinates.rho, ...
                                        polarCoordinates.z);
    end
    

    请注意,这是函数的流线型版本,没有对输入进行错误检查等。现在,让我们做一些示例数据:

    pols = rand(9, 3);  %# A 2-D array of data
    polStruct = struct('theta', pols(:, 1), ...  %# Convert it to a scalar
                       'rho', pols(:, 2), ...    %#   structure of arrays
                       'z', pols(:, 3));
    

    您可以按如下方式访问第五行的rho 值:

    rho5 = pols(5,2);
    rho5 = polStruct.rho(5);
    

    如果您想将极坐标转换为笛卡尔坐标,以下是每种数据类型的转换方法:

    [X,Y,Z] = pol2cart(pols(:,1), pols(:,2), pols(:,3));  %# Calls the built-in one
    [X2,Y2,Z2] = pol2cart(polStruct);  %# Calls the overloaded one
    

    您可以检查它们是否各自给出相同的结果,如下所示:

    >> isequal([X Y Z],[X2 Y2 Z2])
    
    ans =
    
         1   %# True!
    

    【讨论】:

    • 感谢您的详细解答!我想类是要走的路……虽然我担心我不能在代码中使用它,因为害怕吓到不熟悉编程和 OO 范式的代码所有者。
    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 2019-11-27
    相关资源
    最近更新 更多