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

Mit*_*ran 294 ruby ternary-operator conditional-operator

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

例如,这是正确的吗?

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Run Code Online (Sandbox Code Playgroud)

小智 484

它是三元运算符,它的工作方式与C类似(不需要括号).这是一个表达式,如下所示:

if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
Run Code Online (Sandbox Code Playgroud)

但是,在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
Run Code Online (Sandbox Code Playgroud)

请注意,在第一种情况下需要括号(否则Ruby会混淆,因为它认为它puts if 1后面有一些额外的垃圾),但在最后一种情况下它们不是必需的,因为不会出现所述问题.

您可以使用"long-if"表单在多行上提供可读性:

question = if question.size > 20 then
  question.slice(0, 20) + "..."
else 
  question
end
Run Code Online (Sandbox Code Playgroud)

  • @X_Trust在Ruby中,唯一的假值是`nil`和`false`.确实不是很平常. (18认同)

DGM*_*DGM 34

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


puts false ? "true" : "false"
=> "false"
Run Code Online (Sandbox Code Playgroud)

  • 小编辑`put(true?"true":"false")`带括号.否则操作顺序不明确.当我第一次看到这个时,我感到很困惑,因为我把它读作`(put true)?"true":"false"`然后期望`puts`返回布尔值,然后成为字符串值. (4认同)

Way*_*rad 26

您对ERB的使用表明您使用的是Rails.如果是这样,那么请考虑truncate一个内置帮助器,它将为您完成工作:

<% question = truncate(question, :length=>30) %>
Run Code Online (Sandbox Code Playgroud)

  • 这是多年来的事了,但是我对这个答案印象非常深刻,因为它跳过了所有的句法方面,直接进入了提问者试图完成的事情. (11认同)
  • +1,但erb并不一定意味着rails(Sinatra,独立ERB等). (2认同)

the*_*Man 17

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

(true) ? 1 : 0
Run Code Online (Sandbox Code Playgroud)

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

(true)   \
  ? 1    \
  : 0
Run Code Online (Sandbox Code Playgroud)

这是一个简单的例子,但它在处理较长的行时非常有用,因为它可以很好地布置代码.

通过将运算符放在最后一行,也可以使用没有行继续符号的三元组,但我不喜欢或推荐它:

(true) ?
  1 :
  0
Run Code Online (Sandbox Code Playgroud)

我认为这会导致很难读取代码,因为条件测试和/或结果会变得更长.

我读过评论说不要使用三元运算符,因为它令人困惑,但这是不使用某些东西的坏理由.通过相同的逻辑,我们不应该使用正则表达式,范围运算符(' ..'和看似未知的"触发器"变体).如果使用得当它们很强大,所以我们应该学会正确使用它们.


你为什么要把括号括起来true

考虑一下OP的例子:

<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Run Code Online (Sandbox Code Playgroud)

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

<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>
Run Code Online (Sandbox Code Playgroud)

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

<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
                                   : question.question 
%>
Run Code Online (Sandbox Code Playgroud)

或者,更多的书面说法:

<% question = if (question.size > 20)
                question.question.slice(0, 20) + "..."
              else 
                question.question 
              end
%>
Run Code Online (Sandbox Code Playgroud)

很容易认为可读性question.question也会受到严重影响.

  • 如果是多行,为什么不直接使用 if...else...end? (2认同)
  • 因为在 Perl 和 C 中工作了太多年?我使用任何一种,这取决于情况以及一个是否比另一个在视觉上更清晰。有时 if/else 太冗长,有时 ?: 是丑陋的。 (2认同)
  • 因为 `true` 实际上是在用于计算结果为 `true` 或 `false` 的表达式。最好在视觉上对它们进行分隔,因为三元语句会很快变成视觉噪音,降低可读性,从而影响可维护性。 (2认同)