Trying to find vowel strings using Ruby while 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
I'm having trouble finding where this is going wrong. If this program meets a consonant, it stops. Also, how can I solve the same problem with the ".each" method?
source to share
The problem is you never reset j
to zero.
The first time the loop is run while
, which compares the first character string
to each vowel, it j
increases from 0 (for "a") to 4 (for "u"). The second time when the outer loop is executed, it is j
already 4, which means that it then increases to 5, 6, 7 and on and on. vowels[5]
, vowels[6]
etc. all are evaluated before nil
, so characters after the first are never considered vowels.
If you move the line j = 0
inside the outer loop while
, your method works correctly.
The second question, oh .each
, shows that you are already thinking on the right line. while
rarely seen in Ruby, but .each
will definitely be an improvement. As it turns out, you cannot call .each
on String (because the String class does not include Enumerable ), so you have to turn it into a character array first using the String#chars
. With this, your code will 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 kind of thing. The most appropriate here is Array#count
. It takes a block and evaluates it for each element in the array, and then returns the number of elements 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
It's not much shorter. Another great method we can use is Enumerable#any?
. It evaluates the given block for each element in the array and returns true when it finds any element for which the block returns true. Using this code makes our code very 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
(You'll see here that I've added another common Ruby idium, the "percent literal" notation for array creation: %w[ a e i o u ]
This is the usual way to create an array of strings without all those quotes and commas. You can read about it here .)
Another way to do the same would be to use Enumerable#include?
which returns true if the array contains the given element:
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 also has a method include?
, so we can do this instead:
def count_vowels(string)
puts string.chars.count {|char| "aeiou".include?(char) }
end
Not bad! But I saved the best for the latter. Ruby has a great method called String#count
:
def count_vowels(string)
puts string.count("aeiou")
end
source to share