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?

+3


source to share


1 answer


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

      

+11


source







All Articles