I've been looking around and I don't quite find my specific question answered. What makes my question specific is that I'm trying to only use list comprehension.
Question:
With the following code:
[print(k,l,m) for k in range(3) for l in range(2) for m in range(1)]
I get the output:
0 0 0
0 1 0
1 0 0
1 1 0
2 0 0
2 1 0
This works for n=3, or any hardcoded n. However, what I would like to do is:
[print(k1,k2,...,kn) for k1 in range(n) for k2 in range(n-1) .. for kn in range(1)].
I hope someone out there sees the answer immediately-- and thanks!
Edit The solution was posted below, but also to be clear about the format I was hoping for, here's how I used it to print out the encoding tuples:
n=3
[print(x) for x in itertools.product(*[list(range(i)) for i in range(n,0,-1)])]
(Didn't use reverse on the range for simplicity).
You could use itertools.product if you are allowed to :
n=3
list(itertools.product(*[list(range(i)) for i in reversed(range(1, n+1))]))
Someone recently asked a very similar question: "[How to] determine all combinations of flipping a coin without using itertools.product
?" to which I provided an answer for. I wouldn't consider it a duplicate because I believe itertools.product
is the best fit for your particular problem.
You may however be wondering how itertools.product
does the trick. Or maybe you want to encode a different transformation in your recursive expansion. Below, I'll share one possible solution using Python's generators
def product (*iters):
def loop (prod, first = [], *rest):
if not rest:
for x in first:
yield prod + (x,)
else:
for x in first:
yield from loop (prod + (x,), *rest)
yield from loop ((), *iters)
for prod in product ("ab", "xyz"):
print (prod)
# ('a', 'x')
# ('a', 'y')
# ('a', 'z')
# ('b', 'x')
# ('b', 'y')
# ('b', 'z')
Because product
accepts aa list of iterables , any iterable input can be used in the product. They can even be mixed as demonstrated here
print (list (product (['@', '%'], range (2), "xy")))
# [ ('@', 0, 'x')
# , ('@', 0, 'y')
# , ('@', 1, 'x')
# , ('@', 1, 'y')
# , ('%', 0, 'x')
# , ('%', 0, 'y')
# , ('%', 1, 'x')
# , ('%', 1, 'y')
# ]
We could make a program foo
that provides the output posted in your question
def foo (n):
def build_ranges (m):
if m == 0:
return []
else:
return [ range (m) ] + build_ranges (m - 1)
yield from product (*build_ranges (n))
for prod in foo (3):
print (prod)
# (0, 0, 0)
# (0, 1, 0)
# (1, 0, 0)
# (1, 1, 0)
# (2, 0, 0)
# (2, 1, 0)
Or use destructuring assignment to create bindings for individual elements of the product
for (x,y,z) in foo (3):
print ("x", x, "y", y, "z", z)
# x 0 y 0 z 0
# x 0 y 1 z 0
# x 1 y 0 z 0
# x 1 y 1 z 0
# x 2 y 0 z 0
# x 2 y 1 z 0
Other qualities of this product
implementation are discussed in my answer to the question I linked. If you're interested to see how to do this without generators, I provide a purely functional solution to the problem as well.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.