2010-05-14 11 views
8

Ho una lista di valori e voglio metterli in un dizionario che mapperebbe ogni valore al suo indice.modo pythonic per associare elementi di lista ai loro indici

posso farlo in questo modo:

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

questo non è male, ma sto cercando qualcosa di più elegante.

ho incontrato il seguente, ma lo fa il contrario di quello che mi serve:

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

si prega di condividere le vostre soluzioni,
Grazie

EDIT: Python 2.6.4

Per gli elenchi contenenti 1000 elementi la versione dict (zip) è la più veloce, il generatore e le versioni di list comprehension sono praticamente identici e sono ~ 1.5 tempi più lenti e la mappa funzionale (invertita) è notevolmente più lenta.

$ python -mtimeit -s "t = gamma (int (1e3))" "d = dict (zip (t, range (len (t))))"
1000 cicli, meglio di 3: 277 usec per loop

$ pitone -mtimeit -s "t = intervallo (int (1e3))" "d = dict ([(y, x) per x, y in enumerate (t)])"
1000 loop, meglio di 3: 426 usec per loop

$ python -mtimeit -s "t = intervallo (int (1e3))" "d = dict ((y, x) per x, y in enumerate (t)) "
1000 loop, meglio di 3: 437 usec per loop

$ python -mtimeit -s "t = gamma (int (1e3))" "d = dict (mappa (invertita, enumerare (t)))"
100 cicli, meglio di 3: 3.66 msec per loop

Ho provato a eseguire gli stessi test per elenchi più lunghi e più brevi (1e2, 1e4, 1e5) e il tempo per ciclo si riduce linearmente con la lunghezza dell'elenco.

Qualcuno potrebbe conoscere la versione 2.7+?

+0

Sono curioso - quale delle implementazioni è più veloce? A proposito, Chewy, quale versione di Python stai usando? –

risposta

13

È possibile utilizzare un elenco di comprensione (o un generatore, a seconda della versione di Python) per eseguire uno scambio sul posto semplice per il secondo esempio.


Usando una lista di comprensione:

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

Utilizzando un generatore di espressione (Python 2.4 in su):

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

Non è necessario il '[]' in là. 'dict' funziona bene con un'espressione generatore (salva la creazione di una lista intermedia) –

+1

Sì, è per questo che ho scritto" a seconda della versione di Python ". I generatori sono in circolazione da molto tempo (dal 2.4), quindi includerò sia – kibibu

+1

Dove viene utilizzato Python <2.4? – jfs

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

sono tutti i tuoi elementi unici (cioè la tua lista non sarebbe mai 5,6,7,7)? La soluzione dict funzionerà solo se tutti i tuoi elementi sono unici.

Memorizzando l'indice, si stanno essenzialmente duplicando le informazioni, poiché è possibile semplicemente richiedere l'indice corrente dell'elemento nell'elenco. La duplicazione delle informazioni di solito non è l'idea migliore, perché consente la possibilità per un insieme di dati di non sincronizzarsi con l'altro.

Se l'elenco è in fase di modifica, non c'è nulla che impedisca di assegnare accidentalmente lo stesso indice a più di un elemento.

Perché stai cercando di memorizzare il valore dell'indice, quando potresti semplicemente ottenere l'indice dall'elenco?

+0

tutti gli elementi della lista sono unici. Sto memorizzando l'indice per la ricerca rapida in una diversa struttura di dati. –

+0

Sembra un inutile livello di riferimento indiretto se tutti gli elementi sono univoci, prova l'appartenenza con 'in' e l'indice con' index() '. Immagino che immaginate che un dizionario con back-map hash vi darà una ricerca più veloce di 'index()' will. In Python l'ottimizzazione prematura è veramente malvagia, perché le tue intuizioni su "più veloce" sono spesso sbagliate fino a quando non vengono cronometrate. Falla funzionare, poi scopri dove sei lento, la complessità aggiunta non ne vale la pena. – msw

+0

@Dragan, stai modificando il tuo elenco o rimane statico? –

0

Mi piace il dict (zip (t, intervallo (len (t)))) migliore.

+0

Perché? È più veloce? –

+0

È breve, semplice e al punto. – Arafangion

12

In Python2.7 + si può scrivere in questo modo

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

+1 per mostrare la bellezza delle comprensioni di Py3k. – Dustin

2

Come tutti hanno già scritto, in Python 2.6 vorrei considerare quanto segue come il più divinatorio:

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

Eppure, in un momento di frenesia funzionale scriverei:

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