Salomanuel Salomanuel - 3 months ago 7
Ruby Question

keep iterating over and over OVER an array

I realize my communicating skills are not that brilliant (I'm having issues even trying to look up for that), so I let the code speak:

easy_as_123 = ("a".."c").to_a
10.times do |j|
if j >= easy_as_123.length
puts "j is #{j}, letter is #{easy_as_123[j % easy_as_123.length]}"
else
puts "j is #{j}, letter is #{easy_as_123[j]}"
end
end


is there a more elegant and concise solution to keep iterating over and over my [a,b,c] array?

edit, that code I posted works, that's exactly the result I'm looking for, but it's not concise nor good looking, are there methods capable of achieving in more elegant ways that same result?

Answer

Enumerable#cycle is your friend here. Infinite loop:

(?a..?c).cycle.with_index do |letter, j|
  puts "j is #{j}, letter is #{letter}"
end

to break a loop after 10 iterations:

(?a..?c).cycle.with_index do |letter, j|
  break if j >= 10
  puts "j is #{j}, letter is #{letter}"
end

using #take (credits to @Stefan):

(?a..?c).cycle.take(10).each.with_index do |letter, j|
  puts "j is #{j}, letter is #{letter}"
end

other way round:

enum = (?a..?c).cycle
10.times do |j|
  puts "j is #{j}, letter is #{enum.next}"
end

without #cycle:

enum = (?a..?c).to_a
10.times do |j|
  puts "j is #{j}, letter is #{enum[j % enum.length]}"
end

Comments:

  • if is redundant;
  • to_a is redundant, ranges might be enumerated.