Octave中是否支持三目运算符?

7
问题:作为三目运算符,它是否有效?我找不到任何相关的在线文档。我还发现在MATLAB中不可能使用三目运算符,请在这里提供任何建议和答案。 #带有三目运算符的代码
taxes = (income > 50000)*(((income-50000) * 0.20)+(0.10*50000)) + (~(income > 50000))*0.10 *50000
#Condition True and this computation False then this computation

#使用if和else编写代码

if (income) > 50000
#income = income - 50000
#Taxed at 10% (i.e 0.10) for $ 50000
#taxes = 50000 * 0.10
#Rest income will be Taxed at 20% (i.e 0.20)
taxes = 50000 * 0.10 + ((income-50000) * 0.20)
else
#Taxed at 10% (i.e 0.10)
taxes = income * 0.10
endif

输出:

GNU Octave, version 6.1.0
Copyright (C) 2020 The Octave Project Developers.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type 'warranty'.

Octave was configured for "x86_64-w64-mingw32".

Additional information about Octave is available at https://www.octave.org.

Please contribute if you find this software useful.
For more information, visit https://www.octave.org/get-involved.html

Read https://www.octave.org/bugs.html to learn how to submit bug reports.
For information about changes from previous versions, type 'news'.

>> income = 60000;
>> compute_taxes
taxes = 7000
>> income = 50000;
>> compute_taxes
taxes = 5000
>>

4
你的“三元操作代码”在Octave和MATLAB中是有效的。它并不是真正的三元运算符,但它可以产生相同的结果。这段代码比使用if/else语句的优点是它可以处理数组,而不仅仅是标量值。 - Cris Luengo
1
此外,请将终端输出复制粘贴到问题中,而不是上传屏幕截图。请参见此处的原因。 - Cris Luengo
我知道这不是最佳方法,但我试图复制它。虽然我是Octave的初学者,但我已经了解Python,所以我尝试使用这段代码代替。是的,它提供了相同的功能。 - Rocky_Mental
1
那么问题确切是什么?你似乎已经有一些能够实现你想要的功能的代码了? - Luis Mendo
@LuisMendo,Octave 中是否有像 Python 和其他语言中的三元运算符,如果有,它的语法是什么? - Rocky_Mental
2
在Octave中有mergeifelse(它们似乎是相同的),这可能是你想要的(类似于)。 - Luis Mendo
3个回答

5
任何语言中三元运算符的定义与if语句相比有几个重要的不同之处。
其中最主要的区别在于后者是一个"语句"(statement),而三元运算符从定义上来说是一个"表达式"(expression)。换句话说,您期望它返回一个值。 Octave / matlab中的if块不会"返回"一个值(即您不能执行a = if ... endif)。如果您需要某些"返回的"东西,您需要将其分配给循环内部的外部变量,然后在循环外部使用该变量。
第二个重要的区别是,三元运算符应该是可"链接"的(chainable)。也就是说,你应该能够做到"如果这样,那么返回这个值,否则如果那样就返回另一个值",这样在一长串的比较之后,返回单个值。
现在,Octave和Matlab没有这种类型的操作符。但是在Octave中,很容易模拟一个,例如使用单元数组(cells):
M1 = false; M2 = false; M3 = true;
{'expression1', 'expression2', 'expression3', 'fallback'}([ M1, M2, M3, true ]){1}

如果你真的想要,你可以把那种东西变成一个漂亮的匿名函数,它返回第一个使得它的掩码/测试为真的表达式:

tern = @(varargin) reshape(varargin,2,[])(2,:)([reshape(varargin,2,[]){1,:}]){1}
tern( M1, 1, M2, 2, M3, 3, true, 4 )   % ans = 3

在这里,“回退”可以通过在“回退”值之前明确地将一个测试评估为“true”来实现。

注意:在匿名函数中链接两个或多个索引操作的这种风格仅适用于Octave,因为不幸的是Matlab不允许链接操作,例如a(1)(2)。但是,您可以创建一个等效的“正式”的外部函数,在第二次索引之前将中间结果保存到临时变量中;因此,概念上,这种策略也适用于Matlab。


另外,您可以使用稍微不同的语法制作一个更简单的“三元运算符”(好吧,函数),其中您分别传递“测试/掩码”数组、“表达式”和“回退”单元格。例如:

tern2 = @(M,E,F) [E, F]{find([M, true], 1)}
tern2( [M1, M2, M3], {1, 2, 3}, {4} )   % ans = 3

最后,还有一个ifelse函数,它在精神上类似于三元运算符/函数,即ifelse(test, expr_if_true, expr_if_false),但这不是真正的可串联的三元运算符/函数,因为它更适用于基于“true/false掩码”选择两个备选项的情况。

ifelse( [M1, M2, M3], {1, 2, 3}, {4,5,6} )
% ans = { 4, 5, 3 }

2
你可以使用两个短路运算符 &&|| 模拟三元 if 运算符。
考虑以下 if/else 语句:
if condition 
    val = expr1;
else
    val = expr2;
end

t定义为t = @(x) 1;,并将三元if运算符定义为:

condition && t(val = expr1) || t(val = expr2);

在实现三目运算符时,重要的一点是要评估表达式expr1expr2。如果conditiontrue,则不应评估expr2,如果conditionfalse,则不应评估expr1。在类似于ifelse/merge函数中,两个表达式都会在传递到函数之前进行计算,因此不应将ifelse视为真正的三目运算符。
这里有一些基于MATLAB的实现herehere,用于创建递归匿名函数。诀窍在于将表达式包装在lambda中以防止它们被评估。
考虑下面这个计算第n个斐波那契数的函数:
function val = fib(f, n)
  if n <= 2
    val = 1;
  else
    val = f(f, n - 1) + f(f, n - 2));
end

当前提出的技术可用于实现它(已在Octave 6.1.0上测试):

fib = @(f, n, t = @(x) 1, tmp = n <= 2 && t(val = 1) || t(val = f(f, n - 1) + f(f, n - 2))) val;

除了递归匿名函数之外,您可以使用以下内容:

val = {condition && t(tmp = expr1) || t(tmp = expr2), tmp}{2};

然而,这些技巧可能不如 if/else 语句表现更好。


0

考虑实现一个三元条件运算符函数

不确定 Matlab 版本是否能够处理字符串和数组,因为这可能会出现问题

clear ternary
function tern = ternary( test, alternatives); 
  if length( alternatives(:,1)) == 1,, alternatives = alternatives(:); end;
  if test,, tern = alternatives(1,:);
  else,     tern = alternatives(2,:); end
return; end;

一些示例调用

methodss =      ['Runge-Kutta';           'Adams-MLS']; 
adaptive_step = ['adaptive step control'; 'fixed step size'];
report_method = @(selectmethod) [char(    ternary    (selectmethod(1), methodss     )) ' ' ...
                                 char(    ternary    (selectmethod(2), adaptive_step))    ];
%
report_method( [true  false]),; % self-starting = true ;   adaptive step size = false
report_method( [false true ]),; % self-starting = false;   adaptive step size = true

% ans = Runge-Kutta fixed step size
% ans = Adams-MLS   adaptive step control

ternary(2 >  2, [123 456]) %  456
ternary(2 >= 2, [123 456]) %  123

ternary(2 >  2, [123 456; 789 999]) %  789   999
ternary(2 >= 2, [123 456; 789 999]) %  123   456

重要的一点是,三元运算符(test,alternatives)可以在匿名函数中使用,这是Matlab的一个重要卖点。z = test : x : y; - Donovan Roisin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接