尝试使用Ruby while循环查找字符串的元音
def count_vowels(string) vowels = ["a", "e", "i", "o", "u"] i = 0 j = 0 count = 0 while i < string.length do while j < vowels.length do if string[i] == vowels[j] count += 1 break end j += 1 end i += 1 end puts count end
我无法发现出错的地方。 如果该程序遇到辅音,它就会停止。 另外,使用“.each”方法如何解决同样的问题?
问题是你永远不会将j
重置为零。
你的外部while
循环第一次运行,即将string
的第一个字符与每个元音进行比较, j
从0(对于“a”)增加到4(对于“u”)。 然而,第二次外循环运行时, j
已经是4,这意味着它随后会增加到5,6,7,然后再打开。 vowels[5]
, vowels[6]
等都评价nil
,所以第一个之后的字符永远不算作元音。
如果在外部while
循环内移动j = 0
行,则方法可以正常工作。
你的第二个问题,关于.each
,表明你已经在思考正确的方向。 while
很少见到Ruby和.each
肯定会有所改进。 事实certificate,你不能在String上调用.each
(因为String类不包含Enumerable ),所以你必须先用String#chars
方法把它变成一个字符数组。 有了它,您的代码将如下所示:
def count_vowels(string) chars = string.chars vowels = ["a", "e", "i", "o", "u"] count = 0 chars.each do |char| vowels.each do |vowel| if char == vowel count += 1 break end end end puts count end
但是在Ruby中,我们有更好的方法来做这种事情。 这里特别适合的是Array#count
。 它需要一个块并为数组中的每个项目计算它,然后返回块返回true的项目数。 使用它我们可以写一个像这样的方法:
def count_vowels(string) chars = string.chars vowels = ["a", "e", "i", "o", "u"] count = chars.count do |char| is_vowel = false vowels.each do |vowel| if char == vowel is_vowel = true break end end is_vowel end puts count end
但是,这并不短。 我们可以使用的另一个很好的方法是Enumerable#any?
。 它为数组中的每个项计算给定的块,并在找到块返回true的任何项时返回true。 使用它使我们的代码超短,但仍然可读:
def count_vowels(string) chars = string.chars vowels = %w[ aeiou ] count = chars.count do |char| vowels.any? {|vowel| char == vowel } end puts count end
(在这里你会看到我投入了另一个常见的Ruby习语,用于创建数组的“百分比文字”符号: %w[ aeiou ]
。这是创建一个没有所有引号和逗号的字符串数组的常用方法。你可以在这里阅读更多相关信息 。)
另一种做同样事情的方法是使用Enumerable#include?
,如果数组包含给定项,则返回true:
def count_vowels(string) vowels = %w[ aeiou ] puts string.chars.count {|char| vowels.include?(char) } end
…但事实certificate,String有一个include?
方法,所以我们可以这样做:
def count_vowels(string) puts string.chars.count {|char| "aeiou".include?(char) } end
不错! 但是我终于拯救了最好的。 Ruby有一个很棒的方法叫做String#count
:
def count_vowels(string) puts string.count("aeiou") end