我正在尝试使用Test-First材料学习Ruby,并且我在这一点上陷入困境。这是我的代码:
def translate(word)
word=word.split("")
while (!vowel(word[0])) do
first_letter=word[0]
word.each_index do |i|
word[i]=word[i+1]
end
word[word.length-1]=first_letter
end
return word.join + "ay"
end
def vowel(letter)
if letter == ("a" || "e" || "i" || "o" || "u")
return true
end
end
目标是通过查看单词是否以元音开头来实现将单词翻译为“pig latin”的功能。如果是这种情况,该函数只是附加“ay”。如果它以辅音开头,则将第一个字母放在单词的末尾,直到第一个位置有一个元音。
当我将在while循环开始时保存的第一个字母分配到单词的最后一个位置时,我的问题开始了,
word[word.length-1]=first_letter
这会导致程序无限循环。
测试基于字符串“banana”,处理后应读为“ananabay”。 在这种情况下,first_letter包含“b”。所以我测试了将不同的字母分配给单词的最后位置,除了“b”之外的所有字母都很好。 我没有得到的是,while块不依赖于最后一个字母,但是在单词的第一个字母上,它仍然会导致一个无限循环,将“b”分配给word [word.length-1]。
我非常感谢你的一些见解。
答案 0 :(得分:2)
请注意
letter == ("a" || "e" || "i" || "o" || "u")
相当于
letter == "a"
因为("a" || "e" || "i" || "o" || "u")
将评估为第一个真正值,在这种情况下恰好是"a"
。
您需要的是
(letter == "a") || (letter == "e") || (letter == "i") || (letter == "o") || (letter == "u")
也可以写成:
["a","e","i","o","u"].include?(letter)
或
%w(a e i o u).include?(letter)
或
"aeiou".chars.include?(letter)
由于上述逻辑错误,只要字母不是vowel
,nil
方法就会返回"a"
,如果有一个单词不包含元音a
然后,while
循环永远不会终止。因此,需要将其更正为下面的内容。另外,在我们处理它时,让我们将?
添加到方法名称以指示它将返回一个布尔值。
def vowel?(letter)
"aeiou".chars.include?(letter)
end
通过使用如下代码,也可以简化将字符串的第一个字符移动到字符串的结尾:
word = word[1..-1].concat(word[0])
让我们将这个逻辑提取到一个新方法中:
def rotate(word)
word[1..-1].concat(word[0])
end
您还可以通过切换到while
表达式来简化until
循环。
word = rotate(word) until vowel?(word.chars.first)
因此,您的translate
方法可以简化为以下内容:
def translate(word)
word = rotate(word) until vowel?(word.chars.first)
word.concat("ay")
end
还有一个问题,没有任何元音的单词会发生什么,循环将是无限循环。我们需要解决它
def translate(word)
if word.chars.any? { |i| vowel?(i) }
word = rotate(word) until vowel?(word.chars.first)
end
word.concat("ay")
end
完整代码:
def translate(word)
if word.chars.any? { |i| vowel?(i) }
word = rotate(word) until vowel?(word.chars.first)
end
word.concat("ay")
end
def rotate(word)
word[1..-1].concat(word[0])
end
def vowel?(letter)
"aeiou".chars.include?(letter)
end
p translate("banana")
#=> "ananabay"
p ["pig", "banana", "trash", "happy", "duck", "glove"].map(&method(:translate))
#=> ["igpay", "ananabay", "ashtray", "appyhay", "uckday", "oveglay"]