在Python中生成字符串的所有排列,而不使用itertools

在Python中生成字符串的所有排列,而不使用itertools,python,permutation,Python,Permutation,我需要生成字符串中所有可能的字符排列(重复)。如果字符串为“abc”,则输出应为: aaa aab aac abc ... cbc 共同国家评估 建设银行 ccc 我不能使用itertools模块,也不想使用递归(因为这只是一个示例。我真正需要的是输出数百万个排列,我担心内存不足) 我可以这样做: s = 'abc' for c1 in range(0, 3): for c2 in range(0, 3): for c3 in range(0, 3):

我需要生成字符串中所有可能的字符排列(重复)。如果字符串为“abc”,则输出应为:

aaa aab aac abc ... cbc 共同国家评估 建设银行 ccc

我不能使用itertools模块,也不想使用递归(因为这只是一个示例。我真正需要的是输出数百万个排列,我担心内存不足)

我可以这样做:

s = 'abc'

for c1 in range(0, 3):
    for c2 in range(0, 3):
        for c3 in range(0, 3):
            print(s[c1]+s[c2]+s[c3])
基本上,我的for循环数和字符串的字符数一样多。 现在想象一下,例如,如果字符串的长度为10


有更好的方法吗?

如果您担心内存不足,请使用生成器。继续为您的值调用d.next()。它只对小型嵌套循环有效

>>> s = 'abc'
>>> d =( (x,y,z) for x in s for y in s for z in s)
>>> d.next()
'aaa'
>>> d.next()
'aab'
如果您想要所有的值,只需执行以下操作

list(d)
对于任意长度的使用:这将生成与字符串中元素数量相同的组,然后对所有组进行迭代,并不断添加到最终结果中。这就是itertools.product在python中的实现方式。欲了解更多详情,请访问

强制所有结果:

list(product('abc'))

['aaa',
 'aab',
 'aac',
 'aba',
 'abb',
 'abc',
 'aca',
 'acb',
 'acc',
 'baa',
 'bab',
 'bac',
 'bba',
 'bbb',
 'bbc',
 'bca',
 'bcb',
 'bcc',
 'caa',
 'cab',
 'cac',
 'cba',
 'cbb',
 'cbc',
 'cca',
 'ccb',
 'ccc']

解决这个问题的一个简单方法是将字符串中的字符视为不寻常数字系统中的数字。字符串的长度是基线。因此,
'abc'
的排列(带重复)对应于基数3中从
0
3**3-1
的数字,其中
'a'
是数字
0
'b'
1
'c'
2

def permutations_with_repetition(s):
    base = len(s)
    for n in range(base**base):
        yield "".join(s[n // base**(base-d-1) % base] for d in range(base))
样本运行:

>>> for p in permutations_with_repetition("abc"):
    print(p)


aaa
aab
aac
aba
abb
abc
aca
acb
acc
baa
bab
bac
bba
bbb
bbc
bca
bcb
bcc
caa
cab
cac
cba
cbb
cbc
cca
ccb
ccc

如果允许您使用
itertools
,您需要
itertools.product
repeat
关键字参数:
itertools.product(“abc”,repeat=3)

为什么不能使用itertools模块的可能副本?您也可以使用
base**d
而不是
base**(base-d-1)
@StefanPochmann:这会将输出数字按相反的顺序排列,这可能是不可取的(例如,顺序为“aaa”、“baa”、“caa”、“aba”…)。有很多方法可以解决这个问题,我尝试了
reversed()
和列表理解,但仅仅改变指数似乎更容易@DSM,谢谢你指出,我已经修好了。@Blckknght你能解释一下下面陈述背后的数学吗?收益率“.join(s[n//base**(base-d-1)%base]为范围(base)内的d进行连接”)@DhiwakarRavikumar:从数学上讲,这不太复杂
n//base**(base-d-1)%base
是转换为base
base
时,
n
中的第位
d
的数值(必要时带前导零)。
s[…]
是一个索引,它为数字获取合适的字符,
“”。join(…)
将所有单独的数字转换为单个字符串。
>>> for p in permutations_with_repetition("abc"):
    print(p)


aaa
aab
aac
aba
abb
abc
aca
acb
acc
baa
bab
bac
bba
bbb
bbc
bca
bcb
bcc
caa
cab
cac
cba
cbb
cbc
cca
ccb
ccc