这个问题在这里已有答案:
我正在尝试创建一个4d数组并为每个单元格分配变量。
通常我会使用四个“for循环”,但这非常凌乱,占用了大量空间。
我现在在做什么:
for x in range(2):
for y in range(2):
for j in range(2):
for k in range(2):
array[x,y,j,k] = 1 #will be a function in reality
我尝试过使用列表推导,但这只创建了列表,并没有为每个单元格分配变量。
是否有节省空间的方法来运行多个for循环并仅使用几行代码分配变量?
假设你已经创建了一个空(numpy?)数组,你可以使用itertools.product
用值填充它:
import itertools
for x, y, j, k in itertools.product(range(2), repeat=4):
arr[x,y,j,k] = 1
如果不是所有数组的维度相等,您可以单独列出它们:
for x, y, j, k in itertools.product(range(2), range(2), range(2), range(2)):
arr[x,y,j,k] = 1
然而,你可能想知道itertools.product
如何做到这一点。或者您可能希望在递归扩展中编码不同的转换。下面,我将使用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')
因为product
接受一个可迭代列表,所以可以在产品中使用任何可迭代的输入。它们甚至可以如此处所示混合 -
print (list (product (['@', '%'], range (2), "xy")))
# [ ('@', 0, 'x')
# , ('@', 0, 'y')
# , ('@', 1, 'x')
# , ('@', 1, 'y')
# , ('%', 0, 'x')
# , ('%', 0, 'y')
# , ('%', 1, 'x')
# , ('%', 1, 'y')
# ]
我们可以制作一个程序foo
,提供您问题中发布的输出 -
def foo (n, m):
ranges = [ range (m) ] * n
yield from product (*ranges)
for prod in foo (4, 2):
print (prod)
# (0, 0, 0, 0)
# (0, 0, 0, 1)
# (0, 0, 1, 0)
# (0, 0, 1, 1)
# (0, 1, 0, 0)
# (0, 1, 0, 1)
# (0, 1, 1, 0)
# (0, 1, 1, 1)
# (1, 0, 0, 0)
# (1, 0, 0, 1)
# (1, 0, 1, 0)
# (1, 0, 1, 1)
# (1, 1, 0, 0)
# (1, 1, 0, 1)
# (1, 1, 1, 0)
# (1, 1, 1, 1)
或者使用解构赋值为产品的各个元素创建绑定。在您的程序中,只需将print
替换为您的真实功能 -
for (w, x, y, z) in foo (4, 2):
print ("w", w, "x", x, "y", y, "z", z)
# w 0 x 0 y 0 z 0
# w 0 x 0 y 0 z 1
# w 0 x 0 y 1 z 0
# w 0 x 0 y 1 z 1
# w 0 x 1 y 0 z 0
# w 0 x 1 y 0 z 1
# w 0 x 1 y 1 z 0
# w 0 x 1 y 1 z 1
# w 1 x 0 y 0 z 0
# w 1 x 0 y 0 z 1
# w 1 x 0 y 1 z 0
# w 1 x 0 y 1 z 1
# w 1 x 1 y 0 z 0
# w 1 x 1 y 0 z 1
# w 1 x 1 y 1 z 0
# w 1 x 1 y 1 z 1
因为product
被定义为生成器,所以即使在编写更复杂的程序时,我们也可以获得很大的灵活性。考虑这个程序,找到由整数组成的直角三角形,Pythagorean triple。另请注意,product
允许您重复一个可迭代的输入,如下面的product (r, r, r)
所示
def is_triple (a, b, c):
return a * a + b * b == c * c
def solver (n):
r = range (1, n)
for p in product (r, r, r):
if is_triple (*p):
yield p
print (list (solver (20)))
# (3, 4, 5)
# (4, 3, 5)
# (5, 12, 13)
# (6, 8, 10)
# (8, 6, 10)
# (8, 15, 17)
# (9, 12, 15)
# (12, 5, 13)
# (12, 9, 15)
# (15, 8, 17)
有关其他说明以及如何在不使用生成器的情况下查看如何执行此操作的方法,请查看this answer。