我有这个代码,它将打印列表的所有排列:
def permute(iterable,fixed=0):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
print iterable
permute(iterable,fixed+1)
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
现在我想要返回此结果而不是打印它,我发现这样做的最好方法是将打印的内容存储在文件中,然后读取文件,提取数据并将其放入回到我返回的列表中:
import string
from random import *
import os
def randString(minLen=16,maxLen=32,charset=string.ascii_letters+string.digits):
if(minLen>=maxLen):
maxLen=minLen+1
return "".join(choice(charset) for x in range(randint(minLen, maxLen)))
def permutations(iterable):
def permute(iterable,f,fixed=0):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
f.write(''.join(iterable)+" ")
permute(iterable,f,fixed+1)
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
filename="."+randString()+".txt"
f=open(filename,"w+")
permute(list(iterable),f)
f=open(filename,"r+")
result=[]
for i in f.read().split():
result.append([])
for j in i:
result[-1].append(j)
os.remove(filename)
return result
问题是:这会使代码更长,并且至少慢3倍,因为我将所有排列存储在文件中,然后我必须再次遍历每个排列以将其存储回来列表。
我试图通过使用全局变量或通过将结果列表作为参数传递给函数来解决此问题,但它不起作用(因为递归)。
以下代码无效
列表作为参数
def permute2(iterable,fixed=0,permutations=[]):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
return iterable
permutation = permute2(iterable,fixed+1)
if permutation:
permutations.append(permutation)
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
return permutations
全局变量
第一的
def permute(iterable,fixed=0):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
global perms
perms.append(iterable)
permute(iterable,fixed+1)
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
def permutations(iterable):
global perms
perms=[]
permute(list(iterable))
return perms
第二
def permute(iterable,fixed=0):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
addPermutation(iterable)
permute(iterable,fixed+1)
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
def addPermutation(item):
addPermutation.perms.append(item)
def permutations(iterable):
addPermutation.perms=[]
permute(list(iterable))
return addPermutation.perms
这三个坏代码几乎都做同样的事情:它们返回一个包含n的列表!第一次排列的时间。
有没有办法解决这个问题,或者我是否必须使用该文件的代码?
编辑:在@DavidKemp和@ uwain12345的评论之后,我尝试使用了一个类。
def permutations(iterable):
class Permut:
def __init__(self, iterable):
self.iterable = list(iterable)
self.permutations = []
self.permute()
def permute(self,fixed=0):
for i in range(fixed,len(self.iterable)):
self.iterable[fixed:] = [self.iterable[i]] + self.iterable[fixed:i] + self.iterable[i+1:]
if fixed==len(self.iterable)-1:
self.permutations.append(self.iterable)
self.permute(fixed+1)
self.iterable[fixed:] = self.iterable[fixed+1:i+1] + [self.iterable[fixed]] + self.iterable[i+1:]
p = Permut(list(iterable))
return p.permutations
但是我仍然得到与上述代码完全相同的结果(n!第一次排列的次数)。
答案 0 :(得分:2)
你的问题是改变列表iterable
是一个糟糕的策略。对iterbale
所做的更改将始终得到反映,因为它们都是相同的对象。如果我们使用元组代替,我们可以避免这种情况。这是我提出的递归排列代码:
def permute(iterable):
iterable = tuple(iterable)
if len(iterable) <= 1:
yield iterable
return
for i, x in enumerate(iterable):
for sub_permutation in permute(iterable[:i] + iterable[i+1:]):
yield (x,) + sub_permutation
答案 1 :(得分:1)
除非这是一项练习,否则我建议您遵循Patrick Haugh的建议并使用itertools.permutations
。但是,如果您仍然坚持自己滚动而不是print
,请使用yield
关键字:
def permute(iterable, fixed=0):
for i in range(fixed,len(iterable)):
iterable[fixed:] = [iterable[i]] + iterable[fixed:i] + iterable[i+1:]
if fixed==len(iterable)-1:
yield iterable
for e in permute(iterable,fixed+1):
yield e
iterable[fixed:] = iterable[fixed+1:i+1] + [iterable[fixed]] + iterable[i+1:]
# Test out
for e in permute(['a', 'b', 'c']):
print(e)
输出:
['a', 'b', 'c']
['a', 'c', 'b']
['b', 'a', 'c']
['b', 'c', 'a']
['c', 'a', 'b']
['c', 'b', 'a']
yield
语句将&#34;返回&#34;一次一个项目,但不退出该功能。这个函数返回一个生成器,所以请阅读Python生成器以了解更多信息。考虑以下块:
for element in permute(iterable, fixed + 1):
yield element
如果您使用的是Python 3,则可以用
替换该块yield from permute(iterable, fixed + 1)