I have written this code to determine how many a's are present in a given input within a method:
def count_a(word)
count = 0
i = 0
while i < word.length
char = word[i]
if char == "a" || char == "A"
count = 1
end
i = 1
end
return count
end
puts count_a("application") # => 2
puts count_a("bike") # => 0
puts count_a("Arthur") # => 1
puts count_a("Aardvark") # => 3
Can someone better explain why I need the i = 1
at the bottom of the method? I have added to the count in the conditional above, so I just need some further knowledge on how the iteration becomes necessary outside the conditional and within the method.
Thanks!
The code failed to run without the i = 1
CodePudding user response:
Thats a decent first attempt. But its not really Ruby.
Ruby actually has tons of methods that lets you complete this without mutating an external variable:
def count_a(word)
word.each_char # enumerate over the chars
.count { |l| ['a', 'A'].include?(l) } # counts the number of elements yielding a true value.
end
In general methods like while
, until
and loop
should mainly be used when you're dealing with input or streams - in other words when you're not looping across an object with a known length. For everything else use the plethory of methods provided by Enumerable and the other core classes.
Can someone better explain why I need the i = 1 at the bottom of the method?
Because otherwise the loop will run forever since i < word.length
will always be true. But as a rule of thumb if you ever write i = 1
in Ruby you're doing it wrong.
CodePudding user response:
The line i = 1
adds one to i
. If you remove it, then i
will be stuck at 0 forever because you never change it. Therefore, your loop will never terminate (in the case that word.length
is positive).
CodePudding user response:
Any loop needs a test and an update. If the variables in your test never change, why would the loop ever end?
This method could be written far more idiomatically as follows. By downcasing the string first we don't have to check for 'a'
and 'A'
.
def count_a(word)
word.downcase.count('a')
end
As an intermediate solution, you can use #each_char
to iterate over each character in the string.
def count_a(word)
count = 0
word.each_char do |ch|
count = 1 if ch == 'a' || ch == 'A'
end
count
Be aware that a method returns its last expression, an explicit return
is only needed to break control flow and return early from a method.