2013-05-18 8 views
9

mogę permutacji liczb całkowitych tak:Bardziej skuteczny sposób na uzyskanie permutacji całkowitych?

myInt = 123456789 

l = itertools.permutations(str(myInt)) 
[int(''.join(x)) for x in l] 

Czy jest bardziej efektywny sposób, aby uzyskać całkowite permutacje w Pythonie, omijając napowietrznej tworząc łańcuch, a następnie łączenie wygenerowanych krotki? W tym czasie proces łączenia krotek sprawia, że ​​jest on trzykrotnie dłuższy niż list(l).

dodany informacje pomocnicze

myInt =123456789 
def v1(i): #timeit gives 258ms 
    l = itertools.permutations(str(i)) 
    return [int(''.join(x)) for x in l] 

def v2(i): #timeit gives 48ms 
    l = itertools.permutations(str(i)) 
    return list(l) 

def v3(i): #timeit gives 106 ms 
    l = itertools.permutations(str(i)) 
    return [''.join(x) for x in l] 
+0

I wyjaśnione, dłużej niż „listy (l)” – jumbopap

+2

pozwoliłem sobie delegowania pewne rezultaty timeit celu wyjaśnienia problemu OP –

Odpowiedz

0

To daje generator:

import itertools as it 
gen = it.permutations(range(1, 10)) 

Następnie można iteracyjne nad każdej pozycji:

for i in gen: 
    #some code 

lub przekonwertować go do listy, ale zajmie to trochę czasu:

items = list(gen) 

EDIT: wyjaśnić, że chcesz z powrotem liczbę całkowitą, może najszybszym sposobem jest użycie innego leniwe ocena:

gen = (int('%d%d%d%d%d%d%d%d%d' % x) for x in it.permutations(range(1, 10))) 
+0

miałem powiedzieć to samo, ale jego kod jest rzeczywiście znacznie wolniej niż lista wywołań –

+0

W tym procesie nie musiałbym powtarzać każdej liczby całkowitej w generatorze, konwertować liczb całkowitych na ciąg znaków, a następnie powtarzać ponownie, aby dołączyć do każdej krotki, a następnie przekonwertować połączoną krotkę z powrotem na ints? – jumbopap

5

można zrobić:

>>> digits = [int(x) for x in str(123)] 
>>> n_digits = len(digits) 
>>> n_power = n_digits - 1 
>>> permutations = itertools.permutations(digits) 
>>> [sum(v * (10**(n_power - i)) for i, v in enumerate(item)) for item in permutations] 
[123, 132, 213, 231, 312, 321] 

Pozwala to uniknąć konwersji do iz tuple, ponieważ będzie używać pozycji całkowitej w krotce do obliczenia jej wartości (np. (1,2,3) oznacza 100 + 20 + 3).

Ponieważ wartość n_digits jest znany i tym samym w całym procesie, myślę, że można również zoptymalizować obliczeń do:

>>> values = [v * (10**(n_power - i)) for i, v in enumerate(itertools.repeat(1, n_digits))] 
>>> values 
[100, 10, 1] 
>>> [sum(v * index for v, index in zip(item, values)) for item in permutations] 
[123, 132, 213, 231, 312, 321] 

Myślę też, że nie trzeba zadzwonić zip() cały czas, ponieważ nie musimy tę listę:

>>> positions = list(xrange(n_digits)) 
>>> [sum(item[x] * values[x] for x in positions) for item in permutations] 
[123, 132, 213, 231, 312, 321] 
+0

I pierwsza linia jest taka sama jak 'cyfry = [int (x) dla x w str (123)]' – Jared

+0

@Jared: dziękuję, zaktualizowałem odpowiedź. –

+0

To rzeczywiście działa, ale nie sądzę, że jest bardziej wydajne niż v1 podane powyżej. Dziękuję Ci! – jumbopap