简体   繁体   中英

Generate all permutations of a string in Python without using itertools

I need to generate all possible permutations (with repetitions) of the characters in a string. If the string is 'abc', the output should be:

aaa aab aac abc ... cbc cca ccb ccc

I can't use the itertools module and I don't want to use recursion (because this is just an example. What I really need will output millions of permutations and I'm afraid to run out of memory)

I can do it like this:

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])

Basically, I have as many for cycles as the string has characters. Now imagine if the string has length 10, for example!

Is there a better way of doing this?

One easy way to go about this problem is to think of the characters in your string as digits in an unusual number system. The length of the string is the base. So the permutations (with repetition) of 'abc' correspond to the numbers from 0 to 3**3-1 in base 3, where 'a' is the digit 0 , 'b' is 1 and 'c' is 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))

Sample run:

>>> 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

If you were allowed to use itertools , you'd want itertools.product with a repeat keyword argument: itertools.product("abc", repeat=3)

If you are afraid to run out of memory use generators. Keep on calling d.next() for your values. It's only efficient for small nested loops.

>>> s = 'abc'
>>> d =( (x,y,z) for x in s for y in s for z in s)
>>> d.next()
'aaa'
>>> d.next()
'aab'

If you want all the values just do

list(d)

For arbitrary length use: This makes as many groups as elements in strings and then iterates over all of them and keeps on adding to the final result. This is how itertools.product is implemented in python. For more details visit here

def product(x):
        final = [[]]
        l = len(x)
        groups = [list(x)] * l
        for i in groups:
            final = [x+[y] for x in final for y in i]
        for k in final:
            yield ''.join(k)

Force all results:

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']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM