Reputation: 765
is there a way of typing for if like:
var = (cond) ? true : false;
or do we have to use this format?
if (cond)
true
else
false
end
Upvotes: 56
Views: 89725
Reputation: 18609
If anyone is looking for a vectorized ternary (operating on logical arrays and number arrays), here's a really simple one (it is not short-circuiting):
vectorizedTernary = @(cond, resTrue, resFalse) cond.*resTrue + (1-cond).*resFalse
vectorizedTernary([0 1 1 0 0], 1:5, 5:-1:1) % ans = [5 2 3 2 1]
Because I used 1-cond
instead of ~cond
, you can even use it with non-logical conditions, like probabilities:
vectorizedTernary([.2 .7 1], [.1 .2 .3], [0 1/3 2/3]) % ans = [.02 .24 .3]
Upvotes: 0
Reputation: 6240
I found this question when I needed to set my matrix values to 0
or 1
based on an arbitrary condition (e.g. element value is greater than pi
). Turns out it's as easy as:
M > pi
Sure it's less generic than the original question but this corner case may help someone.
Upvotes: 0
Reputation: 754
The following solution has two major advantages over the solutions proposed so far:
if
/else
statement packed in one line, it can also be used in anonymous functions.function out = tern(cond, resTrue, resFalse)
if cond
res = resTrue;
else
res = resFalse;
end
out = res(); %<--- The trick!
The trick to achieve lazy evaluation is that the last line in tern
evaluates the selected result. This way, you can pass anonymous functions to tern
and only the selected will be invoked.
E.g. the following can be invoked without error, when the file with fileName
is not existing:
x = tern( isfile( fileName), @()load( fileName ), ones(10 ));
It should be noted that, when res
is not a anonymous function but of a different basic type (e.g. numeric, character, cell ) in the last line, res()
evaluates to res
itself.
So in summary, the only little difference to a real ternary operator is that it is required to add @()
to the arguments that should only be conditionally evaluated.
Upvotes: 6
Reputation: 11
I know this is late, but for people trying to find an answer I came up with this.
If you want a boolean var = (cond) ? true : false;
you can just do:
var = cond;
If you want a number var = (cond) ? value_if_true: value_if_false;
then do:
var = cond*value_if_true + ~cond*value_if_false;
This is all using that matlab treats true as 1 and false as 0. Therefore that's why the first statement expanded really is
var = cond*1+ ~cond*0;
If you want a text var = (cond) ? text_if_true: text_if_false;
then do:
[repmat(text_if_true,1,cond) repmat(text_if_false,1,~cond)];
Unfortunately you can't mix numerical values with text using this method, just write it with an if-else-end statement.
Upvotes: 1
Reputation: 41
Quick and elegant. I would simply write tern( a>b, a, b) Downside is you have to copy paste everywhere, or have and extra file in the directory
function b = tern(cond, a, b)
if cond
b=a;
end
end
Upvotes: 4
Reputation: 1557
@Leonid Beschastny is correct about the inlining the if-else-end
statement, but If one must, then with any assignment value that can be evaluated as boolean, one can the shortcut boolean operators ||
and &&
:
(cond) && ((var=true_val)||1) || (var=false_val);
Rules:
||
and &&
must be used, NOT |
or &
(var=true_val)
must be followed by ||1
in case true_val == false
(var1=true_val)
while (var2=false_val)
)true_val
and false_val
can be different types provided each then can be evaluated as booleanAlternatively one can do this:
cond && (func1(..)||1) || func2(...);
provided func1
and func2
return a boolean testable value including nothing at all (but no cell arrays!):
Upvotes: 3
Reputation: 31
Replace
c = (x ? a : b)
by
c = subsref({b; a}, substruct('{}', {x + 1}))
x should be a boolean value or 1 or 0.
true or 1 will select a
false or 0 will select b
This should work with all what cells can contain and can also be used in an intricate formular!
Upvotes: 3
Reputation: 21
I use this style frequently:
cond = what < ever;
n = getfield([23,42], {1+(what < ever)}) % for any 1x1-data
s = cell2mat(getfield({'no','yes'}, {1+(what < ever)})) % for nonuniform
it's compact enough to not require a helper function
Upvotes: 2
Reputation: 3397
Hmm... no one has mentioned this
fi = @(varargin)varargin{end-varargin{1}}
somewhere in the docs it is written the `end' is coming to one so this will be more future proof
fi = @(varargin)varargin{length(varargin)-varargin{1}}
Usage :
fi(input('Do you like Matlab ? '),'yes','no')
>> no
If your in the need of inline cases see Mathworks ...
Upvotes: 21
Reputation: 51490
MatLab doesn't have a ternary operator, or any other syntactic sugar for one-line if-statements. But if your if-statement is really simple, you could just write it in one line anyway:
if (cond); casetrue(); else; casefalse(); end
It's not as simple as ternary operator, but still better than writing it in 5 lines of code.
Upvotes: 41
Reputation: 19981
MATLAB doesn't have conditional expressions, but in some situations you can get a similar effect by saying, e.g., var = cond*true_expr + (1-cond)*false_expr
. Unlike C's conditional expression, this will of course always evaluate both true_expr
and false_expr
, and if cond
happens not to be either 0 or 1 (note: false
behaves like 0; true
behaves like 1) you'll get crazy results.
Upvotes: 11
Reputation: 11516
If you only need true or false, you can do what MatlabSorter
suggests. In case you want a real tertiary operator (i.e. a = b ? c : d
), there is none in MATLAB. However, using the file supplied here, you can get close.
Upvotes: 13
Reputation: 1300
You can do
var = 5 > 4;
which will set var to true. Just substitute what ever you need for 5 > 4.
Upvotes: 12