在为变量分配特定字符串时,我的程序无限循环,我无法弄清楚原因

时间:2016-01-26 10:19:22

标签: ruby string loops while-loop indefinite

我正在尝试使用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]。

我非常感谢你的一些见解。

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)

由于上述逻辑错误,只要字母不是vowelnil方法就会返回"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"]