how code a function similar to itertools.product in python 2.5
I have a list of tuples, e.g:
A=[(1,2,3), (3,5,7,9), (7)]
and want to generate al开发者_如何学Cl permutations with one item from each tuple.
1,3,7
1,5,7
1,7,7
...
3,9,7
I can have any number of tuples and a tuple can have any number of elements.
And I can't use itertools.product()
because python 2.5.
docs of itertools.product
have an example of how to implement it in py2.5:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
def product(*iterables):
""" Equivalent of itertools.product for versions < 2.6,
which does NOT build intermediate results.
Omitted 'repeat' option.
product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
"""
nIters = len(iterables)
lstLenths = []
lstRemaining = [1]
for i in xrange(nIters-1,-1,-1):
m = len(iterables[i])
lstLenths.insert(0, m)
lstRemaining.insert(0, m * lstRemaining[0])
nProducts = lstRemaining.pop(0)
for p in xrange(nProducts):
lstVals = []
for i in xrange(nIters):
j = p/lstRemaining[i]%lstLenths[i]
lstVals.append(iterables[i][j])
yield tuple(lstVals)
When playing around with generators, I too found a version of itertools.product
, and it is almost as fast as the (native) library version, while being 100% compatible with it, and it does not build intermediate results:
def product(*args, **kwds):
"Alternative fast implementation of product for python < 2.6"
def cycle(values, uplevel):
for prefix in uplevel: # cycle through all upper levels
for current in values: # restart iteration of current level
yield prefix + (current,)
stack = (),
for level in tuple(map(tuple, args)) * kwds.get('repeat', 1):
stack = cycle(level, stack) # build stack of iterators
return stack
With python 2.7.3, I found the performance to be really good (usually only about a factor of 5-10 slower with essentially the same memory usage).
>>> import itertools as itt
>>> timeit for _ in itt.product(range(20), range(3), range(150)): pass
1000 loops, best of 3: 221 µs per loop
>>> timeit for _ in product(range(20), range(3), range(150)): pass
1000 loops, best of 3: 1.14 ms per loop
EDIT: made code even simpler and Python 3-ready.
The itertools documentation contains full code showing what each function is equivalent to. The product
implementation is here.
精彩评论