Reputation: 25
Background: I am trying to write a simple function that generates a list of calendar days, which I have mostly working except for one if/else loop.
The relevant variables and their initial declaration values:
monthsOfYear = %w[January February March April May June July August September October November December]
currentMonthName = "" # empty string
daysInMonth = 0 # integer
The relevant loop:
monthsOfYear.each do |month| #loop through each month
# first get the current month name
currentMonthName = "#{month}" # reads month name from monthsOfYear array
if ??month == 3 || 5 || 8 || 10 ?? # April, June, September, November
daysInMonth = 30
elsif ??month == 1?? # February
if isLeapYear
daysInMonth = 29
else
daysInMonth = 28
end
else # All the rest
daysInMonth = 31
end
I've marked the part that I'm having trouble with between ?? ?? Basically, I am trying to figure out how to access the numerical value of the index as it loops and test whether that index number matches the few specific cases. I have searched the documentation extensively trying to find a method that returns the index number value (NOT the value stored at x index), in other words I want to be able to read x in Array[x], not what's stored at Array[x]
Perhaps in this specific case it would be better to test whether month == "April" || "June" || "September" || "November" rather than trying to build the case from parsing the array index number?
But in general, what method can be called to find out the index number value? Or is that even possible?
Upvotes: 2
Views: 1177
Reputation: 35483
To get the index of an array item, use the index
method:
monthsOfYear = [ "January", "February", "March", ... ]
monthsOfYear.index("February") #=> 1
If you're looking for date calculations specifically, Ruby has a built-in way:
Date.new(date.year, date.month, -1).mday #=> the number of days in the month
If you're looking to iterate with the month and index, Anthony's answer is correct.
monthsOfYear.each_with_index do |month, index| {
...
# The first loop: month = "January", index = 0
...
}
If you're looking for a way to improve your code, use a case
statement:
case month
when "April", "June", "September", "November"
daysInMonth = 30
when "February"
if isLeapYear
daysInMonth = 29
else
daysInMonth = 28
end
else
daysInMonth = 31
end
In Ruby, you can set anything equal to the result of a case
statement, and also a case statement can match numbers, so it's possible to write:
daysInMonth = case monthsOfYear.index(currentMonthName)
when 3, 5, 8, 10
30
when 1
isLeapYear ? 29 : 28
else
31
end
Upvotes: 2
Reputation: 15967
Joel's answer is a better implementation but to keep with your code and to answer your question, Enumerable has an an each_with_index method (Enumberable#each_with_index):
monthsOfYear.each_with_index do |month, index|
then you can use index in your if/else conditionals. Note that arrays are zero based so January is actually going to be 0
.
Upvotes: 5