列表理解变量分配

时间:2019-03-16 18:05:52

标签: python loops list-comprehension nested-loops

我正在尝试创建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循环并仅用几行代码分配变量?

2 个答案:

答案 0 :(得分:2)

假设您已经创建了一个空(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

答案 1 :(得分:0)

但是,您可能想知道 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接受 iterables 的列表,因此该产品中可以使用任何可迭代的输入。它们甚至可以按此处所示进行混合-

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