解决问题并且对于您可能拥有的任何应用程序都足够通用的简单解决方案是这样的:
def combinations(words, length):
if length == 0:
return []
result = [[word] for word in words]
while length > 1:
new_result = []
for combo in result:
new_result.extend(combo + [word] for word in words)
result = new_result[:]
length -= 1
return result
基本上,这会逐渐在所有组合的内存中建立一棵树,然后返回它们。然而,它是内存密集型的,因此对于大规模组合是不切实际的。
该问题的另一个解决方案确实是使用计数,然后将生成的数字转换为单词列表中的单词列表。为此,我们首先需要一个函数(称为number_to_list()):
def number_to_list(number, words):
list_out = []
while number:
list_out = [number % len(words)] + list_out
number = number // len(words)
return [words[n] for n in list_out]
事实上,这是一个将十进制数转换为其他基数的系统。然后我们编写计数函数;这相对简单,将构成应用程序的核心:
def combinations(words, length):
numbers = xrange(len(words)**length)
for number in numbers:
combo = number_to_list(number, words)
if len(combo) < length:
combo = [words[0]] * (length - len(combo)) + combo
yield combo
这是一个 Python 生成器;使其成为生成器可以使其使用更少的 RAM。把数字变成单词列表后还有一点工作要做;这是因为这些列表需要填充,以便它们处于请求的长度。它会这样使用:
>>> list(combinations('01', 3))
[['0', '0', '0'], ['0', '0', '1'],
['0', '1', '0'], ['0', '1', '1'],
['1', '0', '0'], ['1', '0', '1'],
['1', '1', '0'], ['1', '1', '1']]
如您所见,您会返回一个列表列表。这些子列表中的每一个都包含一系列原始单词;然后,您可能会执行map(''.join, list(combinations('01', 3))) 之类的操作来检索以下结果:
['000', '001', '010', '011', '100', '101', '110', '111']
然后您可以将其写入磁盘;然而,更好的想法是使用生成器的内置优化并执行以下操作:
fileout = open('filename.txt', 'w')
fileout.writelines(
''.join(combo) for combo in combinations('01', 3))
fileout.close()
这只会使用尽可能多的 RAM(足以存储一个组合)。我希望这会有所帮助。