What is the quickest way to get a number with unique digits in python?

Use itertools.permutations:

from itertools import permutations

result = [
    a * 10000 + b * 1000 + c * 100 + d * 10 + e
    for a, b, c, d, e in permutations(range(10), 5)
    if a != 0
]

I used the fact, that:

  • numbers between 10000 and 100000 have either 5 or 6 digits, but only 6-digit number here does not have unique digits,
  • itertools.permutations creates all combinations, with all orderings (so both 12345 and 54321 will appear in the result), with given length,
  • you can do permutations directly on sequence of integers (so no overhead for converting the types),

EDIT:

Thanks for accepting my answer, but here is the data for the others, comparing mentioned results:

>>> from timeit import timeit
>>> stmt1 = '''
a = []
for i in xrange(10000, 100000):
    s = str(i)
    if len(set(s)) == len(s):
        a.append(s)
'''
>>> stmt2 = '''
result = [
    int(''.join(digits))
    for digits in permutations('0123456789', 5)
    if digits[0] != '0'
]
'''
>>> setup2 = 'from itertools import permutations'
>>> stmt3 = '''
result = [
    x for x in xrange(10000, 100000)
    if len(set(str(x))) == len(str(x))
]
'''
>>> stmt4 = '''
result = [
    a * 10000 + b * 1000 + c * 100 + d * 10 + e
    for a, b, c, d, e in permutations(range(10), 5)
    if a != 0
]
'''
>>> setup4 = setup2
>>> timeit(stmt1, number=100)
7.955858945846558
>>> timeit(stmt2, setup2, number=100)
1.879319190979004
>>> timeit(stmt3, number=100)
8.599710941314697
>>> timeit(stmt4, setup4, number=100)
0.7493319511413574

So, to sum up:

  • solution no. 1 took 7.96 s,
  • solution no. 2 (my original solution) took 1.88 s,
  • solution no. 3 took 8.6 s,
  • solution no. 4 (my updated solution) took 0.75 s,

Last solution looks around 10x faster than solutions proposed by others.

Note: My solution has some imports that I did not measure. I assumed your imports will happen once, and code will be executed multiple times. If it is not the case, please adapt the tests to your needs.

EDIT #2: I have added another solution, as operating on strings is not even necessary - it can be achieved by having permutations of real integers. I bet this can be speed up even more.


Cheap way to do this:

for i in xrange(LOW, HIGH):
    s = str(i)
    if len(set(s)) == len(s):
        # number has unique digits

This uses a set to collect the unique digits, then checks to see that there are as many unique digits as digits in total.


List comprehension will work a treat here (logic stolen from nneonneo):

[x for x in xrange(LOW,HIGH) if len(set(str(x)))==len(str(x))]

And a timeit for those who are curious:

> python -m timeit '[x for x in xrange(10000,100000) if len(set(str(x)))==len(str(x))]'
10 loops, best of 3: 101 msec per loop