26

在 VBA 中,我可以执行以下操作:

A = B + IIF(C>0, C, 0)

所以如果 C>0 我得到A=B+C并且 C<=0 我得到A=B

是否有一个运算符或函数可以让我在 MATLAB 代码中内联这些条件?

4

10 回答 10

37

简单地使用 MATLAB 在操作需要时自动转换变量类型这一事实怎么样?例如,逻辑加倍。

如果您的变量是双标量,我相信您的代码可以替换为

a = b + (c > 0) * c;

在这种情况下,运算符(c > 0)1(逻辑类型)无论何时c > 00否则为值。

于 2013-12-23T10:35:20.240 回答
27

Matlab 中没有三元运算符。当然,您可以编写一个函数来完成它。例如,以下函数iif使用 nd 输入作为条件,使用数字和单元格作为结果ab

function out = iif(cond,a,b)
%IIF implements a ternary operator

% pre-assign out
out = repmat(b,size(cond));

out(cond) = a;

对于更高级的解决方案,有一种方法可以创建一个甚至可以执行 elseif 的内联函数,如这篇关于匿名函数恶作剧的博客文章中所述:

iif  = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();

您将此功能用作

iif(condition_1,value_1,...,true,value_final)

用任意数量的附加条件/值对替换点。

它的工作方式是它在值中选择第一个条件为真的值。 2*find(),1,'first')提供值参数的索引。

于 2013-01-30T20:41:30.153 回答
6

对此没有内置解决方案,但您可以自己编写 IIF

function result=iif(cond, t, f)
%IIF - Conditional function that returns T or F, depending of condition COND
%
%  Detailed 
%     Conditional matrix or scalar double function that returns a matrix
%     of same size than COND, with T or F depending of COND boolean evaluation
%     if T or/and F has the same dimensions than COND, it uses the corresponding 
%     element in the assignment
%     if COND is scalar, returns T or F in according with COND evaluation, 
%     even if T or F is matrices like char array.
%
%  Syntax
%    Result = iif(COND, T, F)
%           COND - Matrix or scalar condition
%           T  - expression if COND is true
%           F  - expression if COND is false
%           Result - Matrix or scalar of same dimensions than COND, containing
%                    T if COND element is true or F if COND element is false.
%
if isscalar(cond) 
   if cond 
       result = t;
   else
       result = f;
   end
else
  result = (cond).*t + (~cond).*f;
end  
end
于 2013-01-30T20:27:59.073 回答
6

其他人已经说过?:Matlab中没有三元运算符。作为解决方案,我建议使用这个函数,它采用三个函数而不是值。因此,不必要的计算量被最小化,您可以在开始计算之前检查条件,例如,如果一个值是真正的数字、有限或非零:

function [ out ] = iif( condition, thenF, elseF, in, out)
%iif Implements the ternary ?: operator
%   out = iif (@condition, @thenF, @elseF, in[, out])
%
%   The result is equivalent to:
%   condition(x) ? thenF(x) : elseF(x)
%
%   The optional argument out serves as a template, if the output type is
%   different from the input type, e.g. for mapping arrays to cells and
%   vice versa.
%
% This code is in the public domain.

mask = condition(in);
if nargin <= 4
  out = in;
end

if sum(mask)
  out(mask)  = thenF(in(mask));
end
if sum(~mask)
  out(~mask) = elseF(in(~mask));
end

end

像这样使用它:

f = @(y)(iif(@(x)(x > 3), @(x)(x.^2), @(x)(x/2), y))
f(linspace(0,6,10))
于 2013-05-23T12:08:21.957 回答
3

受乔纳斯回答的启发,下面的函数也适用于混合类型输入和字符,他的函数并不稳定。

function out = iif(cond, a, b)
%IIF implements a ternary operator

    % Use cell output for either char or mixed type input
    if ischar(a) || ischar(b) || ~strcmp(class(a), class(b))
        out = cell(size(cond));
        [out{cond}] = deal(a);
        [out{~cond}] = deal(b);
    else
        % Use array output and logical indexing
        out = repmat(b, size(cond));
        out(cond) = a;
    end
end

编辑:清除了单元分支中的额外条件选项,这些选项显然是先前错误的残余,这可能更快,而且绝对更干净。

于 2014-12-27T21:18:36.877 回答
2

您指的是三元运算符,采用类似 C 的表示法?:。表达方式

tern = bool ? T : F

T如果bool计算结果为真,则返回,F否则。MATLAB 没有三元运算符,但它可以以不同的方式实现为内联表达式。

数组

% cell array version (any type)
tern = {F,T}{bool+1} % only Octave
tern = subsref({F,T}, struct('type', '{}', 'subs', {{bool+1}}))
% vector array version (numeric types only)
tern = [F,T](bool+1) % only Octave
tern = subsref([F,T], struct('type', '()', 'subs', {{bool+1}}))

请注意,TF已被交换,并且使用了不同的括号。向量数组版本是数字类型的特化。MATLAB 不允许直接索引新数组,因此使用subsref.

  • 优点:适用于任何类型和任何值。可以内联使用。
  • 缺点:在将结果返回到 之前ternTF 都被评估。

逻辑运算符和评估

( bool && eval('tern=T') ) || eval('tern=F')

请注意,逻辑运算符是短路的

  • 优点:适用于任何类型和任何值。仅评估一个TF
  • 缺点:仅适用于 Octave。不能内联使用,而是通过变量tern. eval效率不高,但需要。

基本算术

tern = bool*T + !bool*F
  • 优点:可以内联使用。
  • 缺点:仅适用于数字类型,并且在Tor Fare NaNor时可能会失败InfT和,都F被评估。

最大

tern = max(T,F) % bool = T>F

请注意,此解决方案符合初始问题的特定要求max(C,0)

  • 优点:可以内联使用。
  • 缺点:仅适用于数字类型,并且在T或is 时可能F会失败NaNT和,都F被评估。使用受到强烈限制。
于 2020-10-06T18:16:11.697 回答
1

现在有一个tern关于 MathWorks 文件交换的功能:http: //www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m

代码在这里复制:

function varargout = tern(condition, true_action, false_action)

% out = tern(condition, true_action, false_action)
% 
% Ternary operator. If the first input is true, it returns the second
% input. Otherwise, it returns the third input. This is useful for writing
% compact functions and especially anonymous functions. Note that, like
% many other languages, if the condition is true, not only is the false
% condition not returned, it isn't even executed. Likewise, if the
% condition is false, the true action is never executed. The second and
% third arguments can therefore be function handles or values.
%
% Example:
%
% >> tern(rand < 0.5, @() fprintf('hi\n'), pi)
% ans =
%     3.1416
% >> tern(rand < 0.5, @() fprintf('hi\n'), pi)
% hi
%
% It works with multiple outputs as well.
%
% >> [min_or_max, index] = tern(rand < 0.5, ...
%                               @() min([4 3 5]), ...
%                               @() max([4 3 5]))
% min_or_max =
%      5
% index =
%      3
%
% Tucker McClure
% Copyright 2013 The MathWorks, Inc.

    if condition() % Works for either a value or function handle.
        [varargout{1:nargout}] = true_action();
    else
        [varargout{1:nargout}] = false_action();
    end

end
于 2015-09-16T23:43:51.657 回答
1

这更像是对亚历克斯的回答的补充。

Alex的方法在你想返回时不起作用inf

在这些情况下,您通常最终会得到一个0*inf数字,MATLAB 将评估为NaN. 有问题...我们可以使用查找来避免这种乘法。

例如,凸优化中的一个有用的障碍函数是在任何地方都表现得像log正的东西,在-inf其他地方。以下是使用查找创建此类函数的方法:

INF_CONDITION = [0, inf];
fn_logbr = @(x) (x>0)*log(x) - INF_CONDITION( 1+(x<=0) )

内联条件是一种 hack,你会失去惰性求值。你必须要小心。然而,有语义代码真的很好,当你不能保证每个人的环境都一样时,更容易共享你的代码。

于 2016-05-16T09:06:34.953 回答
0

如果您正在寻找一种不会强迫您构建函数并且可以处理相当简单的表达式的选项,那么您可以利用匿名函数。匿名函数返回一个逻辑值,可以是数字 1 或 0。因此,它们可用于与其他数字相乘,以确定它们在表达式之后是否仍然保持值,或者丢失它们的值。

对于您的情况(包括 A、B 和 C 是否为向量):A = B .+ (@() C>0)()

于 2019-06-10T12:45:28.803 回答
-1

使用:

eval('输入;', '输入 = 1;');

在最初可能不存在“输入”的情况下非常有用。

于 2019-05-12T12:42:06.963 回答