Contar dígitos únicos un trazador de líneas (de manera eficiente)

Estoy buscando una manera de contar dígitos únicos de manera eficiente con una sola línea.

Por ejemplo: dado el número entero 623562 , el valor de retorno sería 4 .

Mi forma actual de hacerlo es, dado el entero i , im usando len(set(str(i))) . Crear un conjunto requiere mucho tiempo. Estoy repasando muchos números, así que necesito una forma eficiente.

Además, si alguien puede encontrar una manera de repasar todos los números con x dígitos sin usar el range() (y en una sola línea …), me alegraré. La memoria me limita cuando uso el range porque se crea una lista (supongo).

set s están optimizados para esta creación. A menos que desee desplegar su propia conversión de decimal a cadena (y eso llevaría más de una línea), es el camino a seguir.

range solo asigna memoria en Python 2.x. Para números pequeños como 623562, la memoria no debería ser un problema. Para números más grandes, use xrange en Python 2.xo simplemente cambie a Python 3.x, donde el range genera los números justo a tiempo.

Me está costando mucho creer que len(set(str(num))) no es lo suficientemente rápido para ti. Aquí hay una prueba que hace len(set(str())) de un número aleatorio, muy grande 100,000 veces:

 % python -m timeit -s 'import random' 'for i in range(100000): \ len(set(str(random.randint(199123212312399956789, 1000000099999999123091230000000))))' 10 loops, best of 3: 456 msec per loop 

¡Y una buena parte de ese tiempo está generando números aleatorios! Si realmente necesitas ir más rápido que eso, creo que deberías considerar un lenguaje alternativo.

Aquí hay una manera que evita crear un conjunto cada vez. Todos, excepto la última línea, son códigos de inicialización, por lo que solo suceden una vez:

 >>> from operator import or_ >>> from collections import Counter >>> from functools import reduce >>> bits = {str(i):2**i for i in range(10)} >>> counts = [Counter(format(i,'b'))['1'] for i in range(2**10)] >>> counts[reduce(or_, (bits[c] for c in str(623562)))] 4 

Sin embargo, es aproximadamente 3 veces más lento que el len(set(str(i))) simple, claro y obvio len(set(str(i))) . Como es habitual en Python, hacer las cosas más complicadas o tratar de ser excesivamente inteligente volverá y te morderá el rendimiento.