This isn't sort of like cartesian product; it's exactly like cartesian product.
>>> from itertools import product
>>> list(product([0,1,5], repeat=2))
[(0, 0), (0, 1), (0, 5), (1, 0), (1, 1), (1, 5), (5, 0), (5, 1), (5, 5)]
>>> list(product([2,3], repeat=3))
[(2, 2, 2), (2, 2, 3), (2, 3, 2), (2, 3, 3), (3, 2, 2), (3, 2, 3), (3, 3, 2), (3, 3, 3)]
The polyfill for itertools.product
is the following:
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)
But since you can't use itertools, you might as well take the liberty of writing a slightly more efficient solution to your problem. Since we are just computing the product of n
identical iterables, let's just call it a cartesian exponent:
def cartesian_exponent(li, e=1):
pools = [li] * e
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
return result
Or recursively using yet another incomprehensible list comprehension:
def cartesian_exponent(li, e=1):
if e == 1:
return [[x] for x in li]
else:
return [[x]+y for x in li for y in cartesian_exponent(li, e=e-1)]
Which can be compressed to one line:
def cartesian_exponent(li, e=1):
return [[x] for x in li] if e == 1 else [[x] + y for x in li for y in cartesian_exponent(li, e=e-1)]
But then you would be sacrificing readability for terseness and that's no bueno. The incomprehensible list comprehension is already opaque enough.
Some tests:
>>> cartesian_exponent([0,1,5], e=2)
[[0, 0], [0, 1], [0, 5], [1, 0], [1, 1], [1, 5], [5, 0], [5, 1], [5, 5]]
>>> cartesian_exponent([2,3], e=3)
[[2, 2, 2], [2, 2, 3], [2, 3, 2], [2, 3, 3], [3, 2, 2], [3, 2, 3], [3, 3, 2], [3, 3, 3]]