【问题标题】:How to use conditions within an anonymous function如何在匿名函数中使用条件
【发布时间】:2013-06-29 13:08:49
【问题描述】:

函数可以定义为@(x) x^.2(例如)

但万一,我们有一个函数在不同的时间间隔上采用不同的表示,例如:if abs(x)<3 fun = x^.2 else 0

我们如何使用相同的方式(我的意思是使用 @(x) )来定义这样的函数。

【问题讨论】:

标签: matlab function if-statement inline anonymous-function


【解决方案1】:

有几种方法可以做到这一点。

乘以假:

g = @(x) (abs(x)<3) .* x.^2

或者定义一个合适的函数(最好的方法):

function y = g(x)

    y = zeros(size(x), class(x));

    inds = abs(x)<3;
    y(inds) = x(inds).^2;

end 

或者做一些乱七八糟但很有趣的事情并使用inline-if

iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
g = @(x) iff( ...
    abs(x)<3,  x.^2, ...
        true,  0);

【讨论】:

  • 更多解释:当你想避免计算没有被选中的其他部分时,甚至需要一个适当的函数;例如:iif(x==0;0;1/x)´ here 1/x` 仍然会被评估,即使 x==0。这是一个函数,matlab 仍然希望将所有参数传递给它,因此进行评估。避免这种情况的唯一方法(这就是为什么它是最好的、正确的方法)是使用一个单独的函数,它允许多行和普通的if
  • @GuntherStruyf:是的。在iif() 方法的描述中添加了“inefficnet” :)
  • @GuntherStruyf:嗯。这就是“低效”。打字很难。
  • 主要是作为关于避免错误的评论。它看起来像 if/then/else,但实际上它不是如何执行的。但是,是的,它也是低效的;)
【解决方案2】:

正如@Gunther 在上面的 cmets 中提到的,可以创建一个通用函数来处理简单条件以模仿三级运算符 ?: 来绕过 Matlab 不允许在匿名函数中使用条件的限制(如果你不计算那个凌乱、丑陋、低效但有趣的内联版本:)。

解决方案是通过此链接(可能还有其他一些地方,但 SO 回到了我的谷歌搜索之上,所以认为在此处添加会很好)。 http://www.mathworks.co.jp/matlabcentral/newsreader/view_thread/158054

定义一个函数说 iffifelse 并将其添加到 Matlab 路径。

function result = ifelse(condition,trueResult,falseResult)
    error(nargchk(3,3,nargin));  % check correct number of input args
    if condition
        result = trueResult;
    else
        result = falseResult;
    end

然后像这样使用

predict = arrayfun(@(x) ifelse(x>=0.5,1,0), inputData);

在 OP 的情况下,可以使用类似的东西

arrayfun(@(x) ifelse(abs(x)<3,x^.2,0), data)

【讨论】:

    【解决方案3】:

    这就是我想出的。我有 cases.m 具有以下定义的函数:

    function [ val ] = cases( table )
      [rows,~] = size(table);
      for i = drange(1:rows)
        condition = table{i,1};
        if (ischar(condition) && strcmpi(condition,'else')) || feval(condition)
          val = feval(table{rows,2});
          return
        end
      end
      val={};
    end
    

    函数cases 采用一个包含两列的元胞数组。每个元素都是一个零参数的函数。对于每一行,它采用第一个元素,如果它是字符串“else”或返回真值的函数,则调用第二个元素并返回其值。如果没有行符合条件,则返回一个空单元格。元素是空函数而不是值,因此不需要的情况不会被评估。

    然后我可以这样写 case 表达式:

    w=arrayfun(@(j) cases({ ...
       @() (j==0 || j==n) @() (-1)^j/2; ...
       'else' @() (-1)^j }), 0:n);
    

    这会为从 0 到 n 的值生成一个数组,其中第一个值和最后一个值减半。

    【讨论】:

      【解决方案4】:

      要扩展隐藏在@RodyOldenhuis 答案中的链接,请查看Functional Programming Constructs。该包提供了一套非常全面的功能结构。作者还做了一系列guest posts on the Art of MATLAB blog,展示了这个库背后的很多细节。如果您不想将整个包拉入您的项目,博客文章还包括包中某些功能的匿名单行代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        • 1970-01-01
        • 2017-07-08
        • 1970-01-01
        • 2014-09-11
        • 2022-07-11
        • 2019-04-04
        相关资源
        最近更新 更多