Marisa
Marisa

Reputation: 25

How to access index value of array in conditional test using Ruby

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

Answers (2)

joelparkerhenderson
joelparkerhenderson

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

Anthony
Anthony

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

Related Questions