Reputation: 1161
I have a code that iterates through two ranges. Please see the example below:
(0..6).each do |wday|
(0..23).each do |hour|
p [wday,hour]
end
end
Although this seems very concise and readable, sometimes 5 lines can be too much. One might want to write a more vertically compact code.
(0..6).to_a.product((0..23).to_a).each do |wday,hour|
p [wday, hour]
end
Above was my try, but the code looks very artificial to me. Am I missing something? Does ruby have a preferred way for this type of loop collapsing? If not, are there other alternatives to this workaround?
Upvotes: 2
Views: 76
Reputation: 27207
The following is slightly cleaner version of your loop:
[*0..6].product([*0..23]).each do |wday,hour|
p [wday, hour]
end
This approach does have the disadvantage of expanding the ranges into memory.
I think my preferred way of "collapsing" loops though, especially if the specific loop structure occurs in multiple places, is to turn the nested loops into a method that takes a block and yield
s to it. E.g.
def for_each_hour_in_week
(0..6).each do |wday|
(0..23).each do |hour|
yield wday,hour
end
end
end
for_each_hour_in_week do |wday,hour|
p [wday,hour]
end
This keeps the deep nesting out of the way of your logic, and makes your intent clear.
Upvotes: 4