【问题标题】:Matlab multiple variable assignmentsMatlab多变量赋值
【发布时间】:2014-09-18 07:36:04
【问题描述】:

我想将长度为 2 的向量中的值分配给多个变量。 size() 的输出能够做到这一点:

% works
[m,n] = size([0 0]);

但是将其分成两行是行不通的:

sz = size([0 0]);
[m,n] = sz;
% returns:
%   ??? Too many output arguments.

赋值给变量时丢失的size返回值有什么特别之处?

【问题讨论】:

  • 看看varargoutnargout
  • size() 是一个函数。因此,当您执行size([0 0]) 时,它会进入内部函数并返回两个参数。在第二种情况下,sz 是一个变量,它是一个长度为 2 的向量。现在您尝试将一个变量分配给两个变量。那不会发生。你可以编写自己的函数来做到这一点。
  • 在这里查看多个变量赋值:stackoverflow.com/questions/2740704/…
  • 感谢 Parag S. Chandakkar 我决定编写自己的函数来处理任意长度的向量
  • 哇,丹,我希望我在写那个愚蠢的 eval() 业务之前就知道 varargout

标签: matlab


【解决方案1】:

Matlab 的输出参数以这种方式很有趣。一个函数可以有可变数量的输出,具体取决于“用户”请求的数量。

当你写作时

[m,n] = size([0 0]);

您正在请求两个输出参数。在函数本身内部,这将对应于变量nargout 等于2

但是当你写的时候

sz = size([0 0]);

size 函数识别出它是单个输出参数,并为您提供 mn 作为向量而不是两个单例输出。 这种行为方式(我认为)在 Matlab 中通常不常见。

另请注意,Matlab 不允许多个参数分解向量:

x = [1 1]
[y,z] = x

返回Too many output arguments.

【讨论】:

    【解决方案2】:

    您介绍的自定义函数有点过头了,并且使用了 eval 之类的函数,这被认为是不好的做法。它可以做得更短。这就是你所需要的:

    function [ varargout ] = split( Vector )
    
    varargout = num2cell( Vector );
    
    end
    

    由于varargout,您有一个可变长度的输出参数列表,您无需编辑函数以获得更多参数。

    它适用于向量和矩阵:

    [a,b,c,d] = split( [1,2;3,4] )
    
    a =  1
    
    b =  3
    
    c =  2
    
    d =  4
    

    如果您不喜欢矩阵兼容性,请包含一个条件并检查输入向量的维度。

    【讨论】:

    • 仅第一句话就值得+1。使用varargout 是最流畅的方法。还有一种使用匿名函数的方法不需要单独的脚本(请参阅我的答案)。除非您引入一些 nargin、nargout 检查,否则此解决方案将具有与我相同的陷阱。不同之处在于:您可以引入此类测试,而仅使用匿名函数是不可能的。
    • @RobertP。我也考虑过交易解决方案。但是 OP 显然只是以size 为例,实际上需要拆分更多的值。使用deal 会更难。
    • 我同意我的功能有点矫枉过正
    【解决方案3】:

    如果您出于某种原因不想将其放在单独的函数中,则可以让匿名函数返回多个输出,如下所示:

    split = @(x) deal(x(1), x(2))
    A = zeros(5,3)
    sz = size(A)
    
    [x, y] = split(sz)
       x =  5
       y =  3
    

    deal 函数看到两个左侧参数,从而产生正确的输出。请注意,此功能不会很好地响应错误的输入和输出。查看Loren's blog 了解更多信息。

    【讨论】:

      【解决方案4】:

      您可以将sz 转换为元胞数组,然后从该数组生成comma-separated list

      sz_cell = mat2cell(sz(:), ones(numel(sz),1));
      [m, n] = sz_cell{:}; %// Or [m, n] = deal(sz_cell{:});
      

      【讨论】:

        【解决方案5】:

        size 值并没有什么特别之处。它只是将 sz 作为单个参数处理,因为您将 size 的结果复制到它,这就是它不能有 2 个输出的原因。

        使用由 1 个输出定义的任何其他函数都会得到相同的错误,例如:[m,n] = cos(0) 等。

        【讨论】:

          【解决方案6】:

          我想出了一个办法。感谢 Will Robertson 的回答,我意识到编写函数是真正获得我想要的东西的唯一方法。这里是分开的。

          function [ o1, o2, o3, o4, o5, o6, o7, o8 ] = split( v )
          %SPLIT Splits a vector of bounded length into individual return variables.
          % Split() can handle arbitrarily long input vectors, but only a fixed
          % number of output variables.  @benathon
          %
          % Usage:
          %  vec = [1 2 3 4 5];
          %  [a,b,c,d,e] = split(vec);
          %  [f,g]       = split(vec);
          
          % If you would like to upgrade split() to handle more output variables,
          % simply add more output variables to the function definition and
          % then change this variable
          maxout = 8;
          
          [~,n] = size(v);
          
          if n < nargout
              error('input vector too short for number of output arguments');
          end
          
          % we only need to assign this many output variables
          iterations = min(n,nargout);
          
          
          % Matlab catches "Too many output arguments." before we can
          %if( iterations > maxout )
          %    error('Too many output, edit split.m to easily upgrade');
          %end
          
          
          i = 1;
          while i <= iterations
              expression = sprintf('o%d=v(%d);', i, i);
              eval(expression);
              i = i + 1;
          end
          

          查看 cmets 的使用情况。我也做了一个要点:https://gist.github.com/esromneb/652fed46ae328b17e104

          【讨论】:

            猜你喜欢
            • 2020-07-23
            • 2014-03-22
            • 2012-10-14
            • 2023-03-08
            • 1970-01-01
            • 2010-12-29
            • 1970-01-01
            • 2014-11-27
            • 2012-07-18
            相关资源
            最近更新 更多