例如,给定两个字母A和B,我想生成所有长度为n且具有x A和y B的字符串。
我希望有效地完成这项工作。我考虑过的一种方法是构建A的长度x列表,然后以可能的方式将y B插入列表中。但是插入python列表是线性的,所以当列表变大时,这种方法会很糟糕。
表现目标(这可能是不合理的,但是我的希望):在不到一分钟的时间内生成所有长度为20且字母数相同的A和B的字符串。
编辑:建议使用排列('A'* x,'B'* y)。虽然不是一个坏主意,但它浪费了很多。如果x = y = 4,则多次生成字符串'AAAABBBB'。有没有更好的方法可能只生成一次每个字符串?我已尝试使用set的效果(排列('A'* x,'B'* y))并且它太慢了。
答案 0 :(得分:3)
执行此操作的简单方法如下:
import itertools
def make_sequences(x, y):
return set(itertools.permutations("A" * x + "B" * y))
itertools.permutations()
函数没有考虑输入列表中的重复元素。它最终生成与先前生成的排列重复的排列。因此,使用set()
构造函数会删除结果中的重复元素。
答案 1 :(得分:3)
关于您对性能的关注,这里是您的想法的实际生成器实现(没有insert
)。它找到B
的位置并相应地填充列表。
import itertools
def make_sequences(num_a, num_b):
b_locations = range(num_a+1)
for b_comb in itertools.combinations_with_replacement(b_locations, num_b):
result = []
result_a = 0
for b_position in b_comb:
while b_position > result_a:
result.append('A')
result_a += 1
result.append('B')
while result_a < num_a:
result.append('A')
result_a += 1
yield ''.join(result)
它确实表现得更好。与Greg Hewgill的解决方案(命名为make_sequences2
)相比较:
In : %timeit list(make_sequences(4,4))
10000 loops, best of 3: 145 us per loop
In : %timeit make_sequences2(4,4)
100 loops, best of 3: 6.08 ms per loop
修改强>
广义版本:
import itertools
def insert_letters(sequence, rest):
if not rest:
yield sequence
else:
letter, number = rest[0]
rest = rest[1:]
possible_locations = range(len(sequence)+1)
for locations in itertools.combinations_with_replacement(possible_locations, number):
result = []
count = 0
temp_sequence = sequence
for location in locations:
while location > count:
result.append(temp_sequence[0])
temp_sequence = temp_sequence[1:]
count += 1
result.append(letter)
if temp_sequence:
result.append(temp_sequence)
for item in insert_letters(''.join(result), rest):
yield item
def generate_sequences(*args):
'''
arguments : squence of (letter, number) tuples
'''
(letter, number), rest = args[0], args[1:]
for sequence in insert_letters(letter*number, rest):
yield sequence
用法:
for seq in generate_sequences(('A', 2), ('B', 1), ('C', 1)):
print seq
# Outputs
#
# CBAA
# BCAA
# BACA
# BAAC
# CABA
# ACBA
# ABCA
# ABAC
# CAAB
# ACAB
# AACB
# AABC
答案 2 :(得分:1)
这应该给你一个想法(我已经包含了每一步,所以你可以看到发生了什么):
>>> x = 2
>>> y = 3
>>> lst_a = ['A'] * x
>>> lst_b = ['B'] * y
>>> print lst_a, lst_b
['A', 'A'] ['B', 'B', 'B']
>>> lst_a.extend(lst_b)
>>> lst_a
['A', 'A', 'B', 'B', 'B']
>>> print list(itertools.permutations(lst_a))