I have an array containing multiple arrays (the number may vary) of significant dimensions (an array may contain up to 150 objects).
With the array, I need to find a combination (one element for each sub-array) that matches a condition.
Due to the dimensions, I tried to use Enumerator::Lazy as follows
catch :match do array[0].product(*array[1..-1]).lazy.each do |combination| throw :match if ConditionMatcher.match(combination) end end However, I realize when I call each the enumerator is evaluated and it performs very slowly. I have tried to replace each with methods included in Enumerator::Lazy such as take_while
array[0].product(*array[1..-1]).lazy.take_while do |combination| return false if ConditionMatcher.match(combination) end But also, in this case, the product is evaluated with low performance.
For better performance, even id I don't really like it, I'm thinking to replace product with a nested each loop. Something like
catch :match do array[0].each do |first| array[1].each do |second| array[2].each do |third| throw :match if ConditionMatcher.match([first, second, third]) end end end end Due to the fact that the number of sub-arrays changes from time to time. I'm not sure how to implement it.
Moreover, is there a better way to loop through all the sub-arrays without loading the entire set of combinations?
- Update 1 -
Each sub-array contains an ActiveRecord::Relation on a polymorphic association. Therefore, each element of each combination responds to the same 2 methods (start_time and end_time) each returning an instance of Time.
The matcher checks if all the objects in the combination don't have overlapping times.
ConditionMatcher.match?wherebut they take into consideration multiple factors (and multiple tables) and I have no idea neither where to start from in SQL. So, for now, I think to complete it in Ruby and then, with time, move the logic to SQL.