Reputation: 8086
The ordered_vowel_words
method and ordered_vowel_word?
helper method accept a word and return the word back if the vowels of the word are in the order of (a,e,i,o,u).
I'm having trouble understanding the logic. Particularly how the last block (0...(vowels_arr.length - 1)).all? do...
in the helper method works.
Can someone please explain how this works? I don't understand how all?
is being called on a range
.
def ordered_vowel_words(str)
words = str.split(" ")
ordered_vowel_words = words.select do |word|
ordered_vowel_word?(word)
end
ordered_vowel_words.join(" ")
end
def ordered_vowel_word?(word)
vowels = ["a", "e", "i", "o", "u"]
letters_arr = word.split("")
vowels_arr = letters_arr.select { |l| vowels.include?(l) }
(0...(vowels_arr.length - 1)).all? do |i|
vowels_arr[i] <= vowels_arr[i + 1]
end
end
Upvotes: 0
Views: 219
Reputation: 1
This is my solution to this problem:
def ordered_vowel_words(str)
vowels_s = str.scan(/[aeiou]/)
vowels_sort = str.scan(/[aeiou]/).sort
vowels_s === vowels_sort ? str : ""
end
Upvotes: 0
Reputation: 3999
I've added some comments :)
def ordered_vowel_words(str)
# words is a string with words separated by a whitespace.
# split generates an array of words from a string
words = str.split(" ")
# select only the ordered vowel words from the previous array
ordered_vowel_words = words.select do |word|
ordered_vowel_word?(word)
end
# join the ordered vowel words in a single string
ordered_vowel_words.join(" ")
end
def ordered_vowel_word?(word)
# THESE ARE THE VOWELS YOU FOOL
vowels = ["a", "e", "i", "o", "u"]
# transform the word in an array of characters
letters_arr = word.split("")
# select only the vowels in this array
vowels_arr = letters_arr.select { |l| vowels.include?(l) }
# generate a range from 0 to the length of the vowels array minus 2:
# there is this weird range because we want to iterate from the first vowel
# to the second to last; all? when called on a range returns true if...
(0...(vowels_arr.length - 1)).all? do |i|
# for each number in the range, the current vowel is smaller that the next vowel
vowels_arr[i] <= vowels_arr[i + 1]
end
end
Hope this helped!
EDIT I might add that the last block doesn't feel very Ruby-ish. I may suggest this alternative implementation:
def ordered_vowel_word?(word)
vowels = ["a", "e", "i", "o", "u"]
# transform the word in an array of characters
letters_arr = word.split("")
# select only the vowels in this array
vowels_arr = letters_arr.select { |l| vowels.include?(l) }
# from this array generate each possible consecutive couple of characters
vowels_arr.each_cons(2).all? do |first, second|
first <= second
end
end
require 'rspec/autorun'
describe "#ordered_vowel_word?" do
it "tells if word is ordered" do
expect(ordered_vowel_word?("aero")).to be_true
end
it "or not" do
expect(ordered_vowel_word?("rolling")).to be_false
end
end
Upvotes: 1
Reputation: 1063
(0...(vowels_arr.length - 1))
creates a range from
0 to how many vowels are in the word.all?
iterates over that range and returns true
if all for all
elements of the range some condition is true false otherwise. do |i|
introduces a block with i
as the variable representing
each element of the range created in step 1.i
, it checks if vowels_arr[i] <= vowels_arr[i+1]
is true.Upvotes: 0
Reputation: 33626
The all?
block is essentially iterating over the vowels_arr
array, comparing each value with it's next one. If all the comparisons return true
then all?
will also return true
, which means the array is ordered. If one of the iterations returned false
, the return value of all?
would also be false
, which would mean that the collection is unordered.
You can call all?
on a Rangehttp://www.ruby-doc.org/core-1.9.3/Range.html object because Range
mixes in the Enumerablehttp://www.ruby-doc.org/core-1.9.3/Enumerable.html module, which is the one that defines all?
.
You can verify this by trying the following in irb:
Range.included_modules # => => [Enumerable, Kernel]
Upvotes: 0