2010-05-14 13 views
8

Tengo una lista de valores y quiero ponerlos en un diccionario que asignaría cada valor a su índice.manera pitonica de asociar elementos de lista con sus índices

que pueda hacer de esta manera:

>>> t = (5,6,7) 
>>> d = dict(zip(t, range(len(t)))) 
>>> d 
{5: 0, 6: 1, 7: 2} 

esto no es malo, pero estoy buscando algo más elegante.

que he encontrado lo siguiente, pero hace lo contrario de lo que necesito:

>>> d = dict(enumerate(t)) 
>>> d 
{0: 5, 1: 6, 2: 7} 

Por favor comparta sus soluciones,
Gracias

EDITAR: Python 2.6.4

Para las listas que contienen 1000 elementos, la versión dict (zip) es la más rápida, el generador y la lista de versiones de comprensión son prácticamente idénticos y son ~ 1.5 tiempos más lentos y el mapa funcional (invertido) es considerablemente más lento.

$ pitón -mtimeit -s "t = rango (int (1E3))" "d = dict (zip (t, gama (len (t))))"
1.000 bucles, mejor de 3: 277 usec por lazo

$ pitón -mtimeit -s "t = rango (int (1E3))" "d = dict ([(y, x) para x, y en enumerate (t)])"
1000 loops, mejor de 3: 426 usec por ciclo

$ python -mtimeit -s "t = rango (int (1e3))" "d = dict ((y, x) para x, y en enumerar (t)) "
1000 bucles, mejor de 3: 437 usec por bucle

$ pitón -mtimeit -s "t = rango (int (1E3))" "(mapa (invertido, enumerar (t))) d = dict"
100 bucles, mejor de 3: 3,66 mseg por bucle

Intenté ejecutar las mismas pruebas para las listas más largas y más cortas (1e2, 1e4, 1e5) y el tiempo por ciclo escala linealmente con la longitud de la lista.

¿Podría alguien tiempo py versión 2.7+?

+0

Tengo curiosidad: ¿cuál de las implementaciones es más rápida? Por cierto, Chewy, ¿qué versión de Python estás usando? –

Respuesta

13

Puede usar una lista de comprensión (o un generador, dependiendo de su versión de python) para realizar un simple intercambio en contexto para su segundo ejemplo.


Usando una lista por comprensión:

d = dict([(y,x) for x,y in enumerate(t)]) 

Usando una expresión generadora (Python 2.4 en adelante):

d = dict((y,x) for x,y in enumerate(t)) 
+2

No necesita el '[]' allí. 'dict' funciona bien con una expresión de generador (guarda haciendo una lista intermedia) –

+1

Sí, es por eso que escribí" dependiendo de tu versión de Python ". Los generadores han estado en el mercado durante mucho tiempo (desde 2.4), así que incluiré ambos – kibibu

+1

¿Dónde se usa Python <2.4? – jfs

4
>>> dict((x,i) for i,x in enumerate(t)) 
{5: 0, 6: 1, 7: 2} 
>>> 
2

Son todos sus elementos únicos (es decir, tu lista nunca sería 5,6,7,7)? La solución dict solo funcionará si todos tus elementos son únicos.

Al almacenar el índice, básicamente está duplicando información, ya que podría simplemente consultar el índice actual del artículo en la lista. La duplicación de información generalmente no es la mejor idea, ya que permite la posibilidad de que un conjunto de datos se desincronice con el otro.

Si la lista se está modificando, tampoco hay nada que le impida asignar accidentalmente el mismo índice a más de un elemento.

¿Por qué intenta almacenar el valor del índice, cuando simplemente puede obtener el índice de la lista?

+0

todos los elementos de la lista son únicos. Estoy almacenando el índice para una búsqueda rápida en una estructura de datos diferente. –

+0

Eso suena como un nivel inútil de indirección si todos los elementos son únicos, prueba la membresía con 'in' e index con' index() '. Supongo que imagina que un diccionario respaldado por hashmap le dará una búsqueda más rápida que 'index()'. En Python, la optimización prematura es realmente malvada porque sus intuiciones sobre "más rápido" a menudo son incorrectas hasta que realmente se cronometran. Haz que funcione, luego averigua dónde estás lento, la complejidad añadida no vale la pena. – msw

+0

@Dragan, ¿está modificando su lista o permanece estática? –

0

Me gusta el dict (zip (t, rango (len (t)))) mejor.

+0

¿Por qué? ¿Es más rápido? –

+0

Es corto, simple y al grano. – Arafangion

12

En Python2.7 + se puede escribir como esto

>>> t = (5,6,7) 
>>> d = {x:i for i,x in enumerate(t)} 
>>> print d 
{5: 0, 6: 1, 7: 2} 
+0

+1 por mostrar la belleza de las interpretaciones dict de Py3k. – Dustin

2

Como todo el mundo ya se ha escrito, en Python 2.6 I consideraría los siguientes como los más Pythonic:

>>> dict((x, i) for i, x in enumerate(t)) 
{5: 0, 6: 1, 7: 2} 

embargo, en un momento de frenesí funcional, escribiría:

>>> dict(map(reversed, enumerate(t))) 
{5: 0, 6: 1, 7: 2} 
Cuestiones relacionadas