最近我编写了一个函数,用于生成具有非平凡约束条件的某些序列。这个问题自然而然地带来了一个递归解法。现在问题在于,即使对于相对较小的输入,序列也有数千个,因此我更喜欢将我的算法用作生成器,而不是将其用于填充包含所有序列的列表。
以下是一个示例。假设我们想要使用递归函数计算一个字符串的所有排列。以下朴素算法需要额外的参数“storage”,并且每当它找到一个排列时就将其追加到其中:
def getPermutations(string, storage, prefix=""):
if len(string) == 1:
storage.append(prefix + string) # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], storage, prefix+string[i])
storage = []
getPermutations("abcd", storage)
for permutation in storage: print permutation
请不要关心效率问题,这只是一个示例。
现在我想将我的函数转换为生成器,即产生一个排列而不是将其附加到存储列表中:
def getPermutations(string, prefix=""):
if len(string) == 1:
yield prefix + string # <-----
else:
for i in range(len(string)):
getPermutations(string[:i]+string[i+1:], prefix+string[i])
for permutation in getPermutations("abcd"):
print permutation
这段代码并不起作用(函数的行为就像一个空生成器)。
我有什么遗漏吗? 是否有一种方法可以将上述递归算法转换为生成器,而不是用迭代算法替换它?
yield from getPermutations(string[:i] + string[i+1:])
来替换最后两行代码,这种方式在多个方面上都更加高效! - Manuel Ebertyield from
将要求您使用累加器参数(prefix
)。 - Markus Jarderotstring[i],string[:i]+string[i+1:]
的一对。然后可以这样写:for letter,rest in first_letter_options(string): for perm in getPermuations(rest): yield letter+perm
- Thomas Andrews