Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python itertools skipping ahead

I have a list of lists. Using itertools, I am basically doing

for result in product([A,B],[C,D],[E,F,G]): # test each result

and the result is the desired product, with each result containing one element from each of the lists. My code tests each of the results element-by-element, looking for the first (and best) 'good' one. There can be a very very large number to test.

Let's say I'm testing the first result 'ACE'. Let's say when I test the second element 'C' I find that 'ACE' is a bad result. There is no need to test 'ACF' or 'ACG'. I would want to skip from the failed ACE directly to trying ADE. Anyway to do this without just throwing the unwanted results on the floor?

If I was implementing this with nested for loops, I would be trying to manipulate the for loop indexes inside the loop and that would not be very nice ... but I do want to skip testing a lot of results. Can I skip ahead efficiently in itertools?

like image 285
Mike Avatar asked Nov 14 '22 05:11

Mike


1 Answers

itertools is not the best way to go with the concern you have.

If you just have 3 sets to combine, just loop over and when you fail, break the loops. (If you code is complex, set a variable and break right outside.

for i1 in [A, B]:
  for i2 in [C, D]:
      for i3 in [E, F, G]:
         if not test(i1, i2, i3):
           break

However, if the number of sets that you have is variable, then use a recursive function (backtrack):

 inp_sets = ([A,B],[C,D],[E,F,G])
 max_col = len(inp_sets)
 def generate(col_index, current_set):
     if col_index == max_col:
         if test(current_set):
             return current_set
         else:
             return None
     else:
         found = False
         for item in inp_sets[col_index]:
             res = generate(col_index+1, current_set + [item]):
             if res:
                  return res
             elif (col_index == max_col - 1):
                  # Here we are skipping the rest of the checks for last column
                  # Change the condition if you want to skip for more columns
                  return None

result = generate(0, [])
like image 78
Ehsan Foroughi Avatar answered Nov 17 '22 07:11

Ehsan Foroughi