[英]python: recursive expanding list comprehension
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. 这适用于n = 3或任何硬编码的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 : 如果允许您使用itertools.product:
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
?" 最近有人问一个非常相似的问题: “ [如何]在不使用
itertools.product
情况下确定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. 我不会将其视为重复项,因为我相信
itertools.product
最适合您的特定问题。
You may however be wondering how itertools.product
does the trick. 但是,您可能想知道
itertools.product
如何解决问题。 Or maybe you want to encode a different transformation in your recursive expansion. 或者,您可能想在递归扩展中编码一个不同的转换。 Below, I'll share one possible solution using Python's generators
下面,我将分享使用Python生成器的一种可能的解决方案
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. 因为
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 我们可以制作一个程序
foo
,以提供您问题中发布的输出
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. 我对所链接问题的回答中讨论了该
product
实施的其他质量。 If you're interested to see how to do this without generators, I provide a purely functional solution to the problem as well. 如果您有兴趣了解如何在不使用生成器的情况下执行此操作,那么我也将提供该问题的纯功能解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.