具有多个字符串或条件的简洁控制流程

时间:2016-01-14 04:02:00

标签: ruby

这段代码很长,看起来很难看:

def translate(word)
  if word[0] == "a" || word[0] == "e" || \
     word[0] == "i" || word[0] == "o" || \
     word[0] == "u" || word[0] == "y")
    # move word[0] to the end
    tmp = word.chr
    word = word.reverse.chop.reverse.insert(-1, tmp)
  end
  # add "ay" to end of word
  word.insert(-1, "ay")
end

这种语法是有意义的,但只能检查" a":

def translate(word)
  if word[0] == ("a" || "e" || "i" || "o" || "u" || "y")
    # move word[0] to the end
    tmp = word.chr
    word = word.reverse.chop.reverse.insert(-1, tmp)
  end
  # add "ay" to end of word
  word.insert(-1, "ay")
end

他们是一个更紧凑的方式来做这些多个或者?

2 个答案:

答案 0 :(得分:2)

此代码无效的原因:

word[0] == ("a" || "e" || "i" || "o" || "u" || "y")

...表达式("a" || "b" || ...)的结果只是"a"。在Ruby中,像||这样的布尔运算符返回最后计算的操作数。一旦||运算符找到了一个" truthy" (即第一个不是falsenil)并返回它。如果两个操作数都不真实,则仍然返回最后一个操作数 - 第二个 - 仍然返回:

  nil || true  # => true
  nil || "a"   # => "a"
  nil || false # => false
false || nil   # => nil
  "a" || "e"   # => "a"

表达式"a" || "e" || "i"相当于("a" || "e") || "i"。第一部分评估为"a"(因为"a"是真实的 - "e"永远不会被评估),其中"a" || "i"也会评估为"a",因此,正如您所发现的那样,您最终所做的只是word[0] == "a"

所有这一切的一个整洁和惯用的替代方案是一个简单的正则表达式:

if word =~ /^[aeiouy]/
  # ...
end

P.S。你的其余代码有点奇怪。

首先,如果你想在字符串中附加内容,请不要word.insert(-1, tmp)。只需word << tmp

其次,word.reverse.chop.reverse是删除字符串第一个字符的一种非常折磨的方法。只做word.slice!(0, 1)。这将返回删除的字符,这意味着将字符串的第一个字符移动到结尾就像word << word.slice!(0, 1)一样简单。这些小改动为我们提供了以下代码:

def translate(word)
  if word =~ /^[aeiouy]/
    # move the first character to the end
    word << word.slice!(0, 1)
  end
  word << "ay"
end

P.P.S。您的代码中不需要使用行继续符(\)。当一行以||结尾时,Ruby非常聪明,可以查看表达式其余部分的下一行。

答案 1 :(得分:0)

你可以这样做:

if ['a','e','i','o','u'].include?(word[0])

这将检查word[0]是否匹配数组中的任何元素。

阅读doc了解详情。

示例:

2.1.2-perf :001 > ['a','e','i','o','u'].include?('a')
 => true
2.1.2-perf :002 > ['a','e','i','o','u'].include?('x')
 => false