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
The problem is that you never reset j
to zero.
The first time your outer while
loop runs, which is to compare the first character of string
to each vowel, j
is incremented from 0 (for "a") to 4 (for "u"). The second time the outer loop runs, however, j
is already 4, which means it then gets incremented to 5, 6, 7 and on and on. vowels[5]
, vowels[6]
, etc. all evaluate to nil
, so characters after the first are never counted as vowels.
If you move the j = 0
line inside the outer while
loop, your method works correctly.
Your second question, about .each
, shows that you're already thinking along the right lines. while
is rarely seen in Ruby and .each
would definitely be an improvement. As it turns out, you can't call .each
on a String (because the String class doesn't include Enumerable), so you have to turn it into an Array of characters first with the String#chars method. With that, your code would look like this:
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
In Ruby, though, we have much better ways to do this sort of thing. One that fits particularly well here is Array#count. It takes a block and evaluates it for each item in the array, then returns the number of items for which the block returned true. Using it we could write a method like this:
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
That's not much shorter, though. Another great method we can use is Enumerable#any?. It evaluates the given block for each item in the array and returns true upon finding any item for which the block returns true. Using it makes our code super short, but still readable:
def count_vowels(string)
chars = string.chars
vowels = %w[ a e i o u ]
count = chars.count do |char|
vowels.any? {|vowel| char == vowel }
end
puts count
end
(Here you'll see I threw in another common Ruby idiom, the "percent literal" notation for creating an array: %w[ a e i o u ]
. It's a common way to create an array of strings without all of those quotation marks and commas. You can read more about it here.)
Another way to do the same thing would be to use Enumerable#include?, which returns true if the array contains the given item:
def count_vowels(string)
vowels = %w[ a e i o u ]
puts string.chars.count {|char| vowels.include?(char) }
end
...but as it turns out, String has an include?
method, too, so we can do this instead:
def count_vowels(string)
puts string.chars.count {|char| "aeiou".include?(char) }
end
Not bad! But I've saved the best for last. Ruby has a great method called String#count:
def count_vowels(string)
puts string.count("aeiou")
end