Is there a Matlab conditional IF operator that can

2019-01-09 00:47发布

In VBA I can do the following:

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

so that if C>0 I get A=B+C and C<=0 I get A=B

Is there an operator or function that will let me do these conditionals inline in MATLAB code?

7条回答
叛逆
2楼-- · 2019-01-09 01:10

There is now a tern function on the MathWorks file exchange: http://www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m

The code is reproduced here:

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
查看更多
我想做一个坏孩纸
3楼-- · 2019-01-09 01:11

This is more of an addenum to Alex's answer.

Alex's method doesn't work when you want to return inf

In these cases you often end up getting a 0*inf figure, which MATLAB will evaluate to NaN. Problematic... We can avoid this multiplication using a lookup instead.

As an example, a useful barrier function in convex optimization is something that behaves like log everywhere positive, and -inf elsewhere. Here is how you might create such a function using a lookup:

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

Inline conditionals are a hack, and you lose lazy evaluation. You have to be careful. However, having semantic code is really nice, and its easier to share your code when you can't guarantee everyone's environments are the same.

查看更多
Emotional °昔
4楼-- · 2019-01-09 01:14

Others have said already that there is no ternary ?: operator in Matlab. As a solution I suggest this function, which takes three functions instead of values. Therefore the amount of unnecessary calculations is minimized and you can check conditions before starting calculations, e.g. if a value is really numeric, or finite, or nonzero:

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

Use it like this:

f = @(y)(iif(@(x)(x > 3), @(x)(x.^2), @(x)(x/2), y))
f(linspace(0,6,10))
查看更多
女痞
5楼-- · 2019-01-09 01:16

How about simply using the fact that MATLAB automatically converts variable types when required by the operation? E.g., logical to double.

If your variables are scalar double, your code, I believe, can be replaced by

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

In this case, the operator (c > 0) values 1 (logical type) whenever c > 0 and values to 0 otherwise.

查看更多
女痞
6楼-- · 2019-01-09 01:18

There is no ternary operator in Matlab. You can, of course, write a function that would do it. For example, the following function works as iif with n-d input for the condition, and with numbers and cells for the outcomes a and b:

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

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

out(cond) = a;

For a more advanced solution, there's a way to create an inline function that can even do elseif, as outlined in this blog post about anonymous function shenanigans:

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

You use this function as

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

where you replace the dots with any number of additional condition/value pairs.

The way this works is that it picks among the values the first one whose condition is true. 2*find(),1,'first') provides the index into the value arguments.

查看更多
老娘就宠你
7楼-- · 2019-01-09 01:28

There is no built-in solution for this, but you can write an IIF yourself.

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
查看更多
登录 后发表回答