I can get integer permutations like this:
myInt = 123456789
l = itertools.permutations(str(myInt))
[int(''.join(x)) for x in l]
Is there a more efficient way to get integer permutations in Python, skipping the overhead of creating a string, then joining the generated tuples? Timing it, the tuple-joining process makes this 3x longer than list(l)
.
added supporting information
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]
You can do:
>>> 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]
This avoids conversion to and from a tuple as it'll use the integer's position in the tuple to compute its value (e.g., (1,2,3)
means 100 + 20 + 3
).
Because the value of n_digits
is known and the same throughout the process, I think you can also optimize the computations to:
>>> 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]
I also think we don't need to call zip()
all the time because we don't need that 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]