I was put in a position today in which I needed to enumerate all possible combinations of jagged list. For instance, a naive approach would be:
for a in [1,2,3]:
for b in [4,5,6,7,8,9]:
for c in [1,2]:
yield (a,b,c)
This is functional, but not general in terms of the number of lists that can be used. Here is a more generalized approach:
from numpy import zeros, array, nonzero, max
make_subset = lambda x,y: [x[i][j] for i,j in enumerate(y)]
def combinations(items):
num_items = [len(i) - 1 for i in items]
state = zeros(len(items), dtype=int)
finished = array(num_items, dtype=int)
yield grab_items(items, state)
while True:
if state[-1] != num_items[-1]:
state[-1] += 1
yield make_subset(items, state)
else:
incrementable = nonzero(state != finished)[0]
if not len(incrementable):
raise StopIteration
rightmost = max(incrementable)
state[rightmost] += 1
state[rightmost+1:] = 0
yield make_subset(items, state)
Any recommendations on a better approach or reasons against the above approach?