I have to write a method called consonant_cancel that takes in a sentence and returns a new sentence where every word begins with it's first vowel. The intended output is for given test functions are puts consonant_cancel("down the rabbit hole") #=> "own e abbit ole"
puts consonant_cancel("writing code is challenging") #=> "iting ode is allenging"
but I am getting "own e abbit it ole e" "iting ing ode e is allenging enging ing"
with this code
def consonant_cancel(sentence)
arr = []
vowels = 'aeiou'
words = sentence.split
words.each do |word|
word.each_char.with_index do |char, i|
if vowels.include?(char)
arr << word[i..-1]
end
end
end
return arr.join(' ')
end
puts consonant_cancel("down the rabbit hole") #=> "own e abbit ole"
puts consonant_cancel("writing code is challenging") #=> "iting ode is allenging"
Can you guys help me to debug it.
CodePudding user response:
If we adding in a puts
to see what's happening in your loop:
def consonant_cancel(sentence)
arr = []
vowels = 'aeiou'
words = sentence.split
words.each do |word|
word.each_char.with_index do |char, i|
if vowels.include?(char)
puts char
arr << word[i..-1]
end
end
end
return arr.join(' ')
end
Then running consonant_cancel "hello world"
we see:
irb(main):044:0> consonant_cancel "hello world"
e
o
o
=> "ello o orld"
irb(main):045:0>
You'll see the same issue with any word with multiple consonants, because of the way you're looping over the characters in a word and checking for consonants.
An easier way to accomplish this would be with regular expressions.
words.split.map { |w| w.sub(/^[^aeiou]*/i, "") }.join(' ')
CodePudding user response:
word.each_char.with_index
This loop iterates all chars (and vowels) of the word. break
it after the first vowel found, so it does not repeat the side-effects for subsequent vowels of this word.
As an alternative, here's another regex-based solution
def consonant_cancel(sentence)
sentence.scan(/\b[^aeiou]*(. ?)\b/i).join(" ")
end
CodePudding user response:
You can use String#gsub with a regular expression. There is no need to break the string into pieces for processing and subsequent recombining.
def consonant_cancel(str)
str.gsub(/(?<![a-z])[a-z&&[^aeiou]] /i,'')
end
consonant_cancel("down the rabbit hole")
#=> "own e abbit ole"
consonant_cancel("writing code is challenging")
#=> "iting ode is allenging"
See the section "Character Classes" in the doc for Regexp for an explanation of the &&
operator.
We can write the regular expression in free-spacing mode1 to make it self-documenting.
/
(?<! # Begin a negative lookbehind
[a-z] # Match a lowercase letter
) # End negative lookbehind
[a-z&&[^aeiou]] # Match one or more lowercase letters other than vowels
/ix # Invoke case-indifference and free-spacing modes
The negative lookahead ensures that no string of letters immediately preceded by a letter is matched. The line
[a-z&&[^aeiou]]
can alternatively be written
[b-df-hj-np-tv-z]
1. See the section "Free-Spacing Mode and Comments" in the doc for Regexp
.
CodePudding user response:
You don't have to write such a big coding. You could write the following code to accomplish what you have wanted.
Input
a="down the rabbit hole"
Code
p a.split
.map { |x| x.sub(/[^aeiou]/, "") }
.join(" ")
Output
"own he abbit ole"