是否有可以像 VBA 的 IIF 一样内联放置的 Matlab 条件 IF 运算符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14612196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a Matlab conditional IF operator that can be placed INLINE like VBA's IIF
提问by Lance Roberts
In VBA I can do the following:
在 VBA 中,我可以执行以下操作:
A = B + IIF(C>0, C, 0)
so that if C>0 I get A=B+C
and C<=0 I get A=B
所以如果 C>0 我得到A=B+C
并且 C<=0 我得到A=B
Is there an operator or function that will let me do these conditionals inlinein MATLAB code?
是否有运算符或函数可以让我在 MATLAB 代码中内联执行这些条件?
采纳答案by Jonas
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
:
Matlab 中没有三元运算符。当然,您可以编写一个函数来执行此操作。例如,以下函数iif
与条件的 nd 输入以及结果a
和的数字和单元格一起工作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:
对于更高级的解决方案,有一种方法可以创建一个甚至可以执行 elseif 的内联函数,如这篇关于匿名函数恶作剧的博客文章所述:
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.
它的工作方式是从值中选择第一个条件为真的值。 2*find(),1,'first')
提供值参数的索引。
回答by Alex
How about simply using the fact that MATLAB automatically converts variable types when required by the operation? E.g., logical to double.
简单地使用 MATLAB 在操作需要时自动转换变量类型的事实如何?例如,逻辑加倍。
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.
在这种情况下,操作符(c > 0)
值1
(逻辑类型)everywherec > 0
和values to 0
else。
回答by quazgar
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 beforestarting calculations, e.g. if a value is really numeric, or finite, or nonzero:
其他人已经说过?:
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
Use it like this:
像这样使用它:
f = @(y)(iif(@(x)(x > 3), @(x)(x.^2), @(x)(x/2), y))
f(linspace(0,6,10))
回答by kol
There is no built-in solution for this, but you can write an IIF yourself.
对此没有内置解决方案,但您可以自己编写 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
回答by hugovdberg
Inspired by Jonas' answer the function below also works for mixed type input and chars, for which his function isn't stable.
受乔纳斯回答的启发,下面的函数也适用于混合类型输入和字符,因为他的函数不稳定。
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
Edit: weeded out the extra conditional options in the cell branch, which were apparently remnants of a previous mistake, this is probably faster, and definitely cleaner.
编辑:清除单元格分支中的额外条件选项,这些选项显然是先前错误的残余,这可能更快,而且绝对更干净。
回答by Alex
There is now a tern
function on the MathWorks file exchange:
http://www.mathworks.com/matlabcentral/fileexchange/39735-functional-programming-constructs/content/tern.m
tern
MathWorks 文件交换现在有一个函数: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
回答by Christian Chapman
This is more of an addenum to Alex's answer.
这更像是对亚历克斯答案的补充。
Alex's method doesn't work when you want to return inf
当你想返回时,Alex 的方法不起作用 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.
在这些情况下,您通常最终会得到一个0*inf
图形,MATLAB 会将其计算为NaN
。有问题......我们可以使用查找来避免这种乘法。
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:
例如,凸优化中有用的障碍函数的行为类似于log
处处正值和-inf
其他处。以下是使用查找创建这样一个函数的方法:
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.
内联条件是一个黑客,你失去了懒惰的评估。你必须要小心。然而,拥有语义代码真的很好,当你不能保证每个人的环境都一样时,它更容易共享你的代码。
回答by TheBrenny
If you're looking for an option that doesn't force you to build a function and can take care fairly simple expressions, you can take advantage of anonymous functions. The anonymous function returns a logical, which can be a numeral 1 or 0. Because of this, they can be used to multiply with other numbers to determine if they still hold a value after the expression, or lose their value.
如果您正在寻找一种不会强迫您构建函数并且可以处理相当简单的表达式的选项,您可以利用匿名函数。匿名函数返回一个逻辑值,它可以是数字 1 或 0。因此,它们可用于与其他数字相乘,以确定它们是否在表达式后仍然保留值,或者丢失其值。
For your case (including if A, B, and C are vectors or not): A = B .+ (@() C>0)()
对于您的情况(包括 A、B 和 C 是否为向量): A = B .+ (@() C>0)()
回答by user11488510
Using:
使用:
eval('input;', 'input = 1;');
eval('input;', 'input = 1;');
is very helpful where 'input' might not exist in the first place.
在最初可能不存在“输入”的情况下非常有用。