如何在Ruby中使用条件运算符(?:)?


303

? :在Ruby中如何使用条件运算符()?

例如,这是正确的吗?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

1
是的,我想,但我也认为您可以通过以下方法完成此任务: question=question[0,20] 如果它小于20,则不会对其进行任何更改。
DGM 2010年

如果长度大于20,我还需要添加一个“ ...”
Mithun Sreedharan

1
小心盲切掉给定列上的一条线。您最终可能会在中途删掉一个单词,然后附加省略号('...'),看起来很糟糕。而是查找附近的标点符号或空格字符,然后在此处截断。只有在附近没有更好的断点时,才应截断中间单词。
Tin Man 2010年

Answers:


496

它是三元运算符,其工作方式类似于C(不需要括号)。该表达式的工作方式如下:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

但是,在Ruby中,if表达式也是这样的:if a then b else c end=== a ? b : c,除了优先级问题。两者都是表达式。

例子:

puts (if 1 then 2 else 3 end) # => 2

puts 1 ? 2 : 3                # => 2

x = if 1 then 2 else 3 end
puts x                        # => 2

请注意,在第一种情况下需要括号(否则Ruby会感到困惑,因为它认为它puts if 1后面有一些多余的垃圾),但在最后一种情况下则不需要,因为不会出现上述问题。

您可以在多行中使用“ long-if”形式以提高可读性:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end

放0?结果2:3也给出2。这是为什么?
X_Trust

18
@X_Trust在Ruby中,唯一的错误值是nilfalse。确实不是很平常。
Kroltan

35
puts true ? "true" : "false"
=> "true"


puts false ? "true" : "false"
=> "false"

简洁但解释了它的作用。
Tin Man

4
puts (true ? "true" : "false")带有括号的小修改。否则,操作顺序不清楚。当我初次阅读此内容时,我很困惑,因为我 (puts true) ? "true" : "false"希望随后puts返回布尔值,然后该布尔值成为字符串值。
Fresheyeball

26

您对ERB的使用表明您在Rails中。如果是这样,请考虑truncate使用内置的帮助程序来为您完成这项工作:

<% question = truncate(question, :length=>30) %>

这很棒!我到底想干什么!
Mithun Sreedharan

11
这已经晚了几年,但是这个答案让我印象深刻,因为它超越了所有语法方面,并且直逼提问者试图完成的工作。
迈克·巴比

2
+1,但erb不一定暗示有导轨(Sinatra,独立ERB等)。
福克斯·威尔逊

17

@pst给出了一个很好的答案,但是我想提一下,在Ruby中,三元运算符写在一行上是语法正确的,这与Perl和C不同,我们可以在多行上写它:

(true) ? 1 : 0

通常,如果您尝试将其拆分为多行,Ruby会引发错误,但是您可以\在行尾使用行继续符号,Ruby会很高兴的:

(true)   \
  ? 1    \
  : 0

这是一个简单的示例,但是在处理更长的行时可能会非常有用,因为它可以使代码保持良好的布局。

通过将运算符放在行的最后,也可以使用不带行连续字符的三进制,但是我不喜欢或不建议这样做:

(true) ?
  1 :
  0

我认为随着条件测试和/或结果变得更长,这将导致很难阅读代码。

我读过一些评论,其中说不要使用三元运算符,因为这很令人困惑,但这是不使用某些东西的不好的理由。按照相同的逻辑,我们不应使用正则表达式,范围运算符(“ ..'和看似未知的“触发器”变体)。如果正确使用它们,它们功能强大,因此我们应该学习正确使用它们。


你为什么要放括号true

考虑OP的例子:

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>

包装条件测试有助于使其更具可读性,因为它在视觉上将测试分开:

<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>

当然,通过明智地添加空白,可以使整个示例更具可读性。这未经测试,但您会明白的:

<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
                                   : question.question 
%>

或者,更习惯地写:

<% question = if (question.size > 20)
                question.question.slice(0, 20) + "..."
              else 
                question.question 
              end
%>

很容易争论可读性question.question也会受到严重影响。


1
如果是多行,为什么不使用if ... else ... end?
韦恩·康拉德

1
因为在Perl和C中工作了太多年了?根据情况以及一个在视觉上是否比另一个更清晰,我会使用其中一个。有时候,如果/否则太冗长,有时?:很难看。
Tin Man 2010年

1
@WayneConrad如果在此答案中至少解释了一个问题:stackoverflow.com/a/4252945/2597260比较使用多行if /三元运算符的几种方法:gist.github.com/nedzadarek/0f9f99755d42bad10c30
DarekNędza

你为什么要放括号true
扎克

1
因为true实际上是坐在什么地方,所以它的计算结果就是truefalse。最好以视觉方式对这些进行定界,因为三元语句会迅速演变为视觉噪声,从而降低影响可维护性的可读性。
Tin Man

3

一个简单的示例,其中操作员检查玩家的ID是否为1,并根据结果设置敌人ID

player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2

我找到了有关该主题的帖子,似乎很有帮助。


4
为什么不enemy_id = player_id == 1 ? 2 : 1呢?
亚伦·布伦库什

1
@AaronBlenkush感谢您的优雅输入。我仍处于菜鸟阶段,可能是原因:)
devwanderer


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.