Reputation: 47
I'm very new to Ruby and would like to know how to automate an empty array to show the entered data to sort alphabetically and also alternate each entry between uppercase and lowercase. I have seen similar posts on this site that describe how to accomplish this but can't seem to get this to work.
Below is my code, and this is using the example here: How to have the user input alternate between uppercase and lowercase in Ruby?
Currently my code first alternates the uppercase and lower case, then sorts it alphabetically (creating two lists). What I want is just one list that is in alphabetical order and alternates the upper and lower case. I hope this makes sense, thank you for your time!
puts "Welcome to the word list!"
words = []
5.times do
puts "Please enter a word:"
words << gets.chomp
end
words.each_with_index do |word, index|
if index.even?
puts word.upcase
else
puts word.downcase
end
end
puts "Here are your words:"
puts words.sort
Upvotes: 2
Views: 1841
Reputation: 110745
I would do it like this:
enum = [:upcase, :downcase].cycle
#<Enumerator: [:upcase, :downcase]:cycle>
5.times.with_object([]) do |_,words|
puts "Please enter a word:"
words << gets.chomp.send(enum.next)
end
If "dog\n"
, "cat\n"
, "pig\n"
, "cow\n"
and "owl\n"
were entered, this would return:
["DOG", "cat", "PIG", "cow", "OWL"]
As you are new to Ruby, I would be surprised if you understand what I've done on first reading. If you break it down, however, it's not so bad. If you work on this until you understand it, I guarantee you will make a big jump in your understanding of the language.
If you examine the docs for Array#cycle (which returns an instance of the class Enumerator
) and Enumerator#next you will find:
enum.next #=> :upcase
enum.next #=> :downcase
enum.next #=> :upcase
enum.next #=> :downcase
...
The dispatching of methods to receivers is the job of Object#send.Whenever you invoke a method (say [1,2] << 3
) Ruby sends the method (name) and its arguments to the receiver ([1,2].send(:<<, 3
).
So you see, the method name :upcase
is sent to all
even-numbered words and:downcase
is sent to all odd-numbered words.
The method Enumerator#with_object is a more Ruby-like way of producing the result:
words = []
5.times do
puts "Please enter a word:"
words << gets.chomp.send(enum.next)
end
words
Notice that with_object
saves two steps, but it also has the advantage of restricting the scope of the array words
to the block.
A related method, Enumerable#each_with_object could be used in place of each_object
's (because the class Enumerator
include
's the Enumerable
module) and must be used when the receiver is not an enumerator (when the receiver is an array or hash, for example).
Lastly, you could write the block variables as |i,words|
, where i
is the index (produced by Integer#times) that ranges from 0
to 4
. It is common practice to replace a block variable that is not used in the block with an underscore, in part to so-inform the reader. Note that _
is a perfectly legitimate local variable.
Upvotes: 2
Reputation: 34336
First of all, you will get different results in these two cases:
1. sort the words first and then apply your alternate upcase/downcase logic.
2. apply your alternate upcase/downcase logic first, then sort the words.
because if you sort the words first, the index of the words in the original input array will be changed. So, it will have impact on your upcase/downcase logic as you are doing that based on the index of the word in the input array.
So, it depends on your original requirement whether you want to sort the words first, or at the end.
This is the first method:
puts "Welcome to the word list!"
words = []
results = []
5.times do
puts "Please enter a word:"
words << gets.chomp
end
words.sort.each_with_index do |word, index| # sort the input words first, then loop through
# accumulate the results in the results array
if index.even?
results << word.upcase
else
results << word.downcase
end
end
puts "Here are your resulting words: "
puts results
If you want the second one, you can just do the sort at the end.
Upvotes: 2