我在理解Python在下面介绍的情况下是如何工作的遇到了一些困难。
我正在递归计算列表的所有排列,并且我想返回包含所有这些排列的列表列表。如果我只是打印出来,代码工作正常,但是如果我尝试扩展最终的 [结果],我最终会得到一个与我的输入列表具有相同值的列表列表(抱歉重复单词列表)
这是我的代码:
def swap(l, i, j):
l[i], l[j] = l[j], l[i]
def compute(l):
if not len(l):
print 'no list'
start, end = 0, len(l) - 1
return _compute(l, start, end)
def _compute(l, start, end):
res = []
if start == end:
return [l]
else:
for i in range(start, end+1):
swap(l, start, i)
res.extend(_compute(l, start+1, end))
swap(l, start, i) # backtrack
return res
l = [1,2,3]
print compute(l)
结果是:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
就像我说的,如果我只是打印出结果,它会按预期工作:
def swap(l, i, j):
l[i], l[j] = l[j], l[i]
def compute(l):
if not len(l):
print 'no list'
start, end = 0, len(l) - 1
_compute(l, start, end)
def _compute(l, start, end):
if start == end:
print l
else:
for i in range(start, end+1):
swap(l, start, i)
_compute(l, start+1, end)
swap(l, start, i) # backtrack
l = [1,2,3]
compute(l)
输出:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]
为什么?
Python 可以处理对象。变量是指对象。如果将列表添加到结果列表中,然后进行修改,则结果中的列表将反映这些更改。
因此,您至少应该制作一个浅拷贝。例如,您可以使用:
def _compute(l, start, end):
res = []
if start == end:
return [l[:]] # make a shallow copy
else:
for i in range(start, end+1):
swap(l, start, i)
res.extend(_compute(l, start+1, end))
swap(l, start, i) # backtrack
return res
l = [1,2,3]
print compute(l)
尽管如此,这个代码片段仍然效率很低,而且难以理解。请注意,not(len(l))
不检查对象是否有len(..)
:它检查len(l)
是否为零。因此,您应该使用 isinstance(..)
.
更有效的方法是构造一次res
列表,然后将其传递到系统集合结果中。例如:
def _compute(l):
def _calc(start, end, res):
if start < end-1:
for i in range(start,end):
swap(l,start,i)
_calc(start+1, end, res)
swap(l,start,i)
else:
res.append(l[:])
return res
return _calc(0, len(l), [])