def powerset(x):
total1 = [[]]
total2 = [[]]
for a in x:
for b in total1:
c = list(b + [x[a]])
total2.append(c)
total1 = total2
# the total 1 and total 2 system should prevent it
# from creating an infinite loop when we add to the total.
print (total1)
f = [1,2,3]
g = powerset(f)
print (g)
这是我尝试为数据科学课程的入门创建一个powerset。当我运行此命令时,我会在内存不足之前收到[[], [2]]
作为输出。我不明白为什么它会返回[[], [2]]
,也不知道为什么它会耗尽内存,因为total1
在循环之外被更改。
变量g
应返回f
。
有人可以解释我做错了吗?
答案 0 :(得分:1)
在第一个循环后设置total1 = total2
,这意味着 total1
和total2
引用相同的列表。
所以在第二个循环中,您迭代total1
并更新total2
,即同一个列表。在Python(以及大多数编程语言)中,更改您迭代的集合是危险的,因此您不断向列表中添加项目,从而使循环越来越长。
代码本身并不存在问题。我们可以把它写成:
def powerset(x):
result = [[]]
for xi in x:
xil = [xi]
for j in range(len(result)):
result.append(result[j] + xil)
return result
虽然它可能看起来像是一些语法重写,但我们在j
上迭代range(len(result))
。请注意,我们只计算len(result)
一次,当我们启动for
循环时,之后,我们可以安全地更新total
,因为范围对象不会改变了。
然后产生:
>>> powerset([1,2,3])
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
请注意,我们可以使用itertools.combinations
函数来简化生活:
from itertools import combinations
def powerset(x):
xl = list(x)
for r in range(len(xl)+1):
for ri in combinations(xl, r):
yield ri
然后我们获得:
>>> list(powerset([1,2,3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]