Converti un elenco in un dizionario in Python


191

Diciamo che ho un elenco ain Python le cui voci sono convenientemente associate a un dizionario. Ogni elemento pari rappresenta la chiave del dizionario e il seguente elemento dispari è il valore

per esempio,

a = ['hello','world','1','2']

e vorrei convertirlo in un dizionario b, dove

b['hello'] = 'world'
b['1'] = '2'

Qual è il modo sintatticamente più pulito per ottenere questo risultato?


Risposte:


272
b = dict(zip(a[::2], a[1::2]))

Se aè grande, probabilmente vorrai fare qualcosa di simile al seguente, che non rende alcun elenco temporaneo come sopra.

from itertools import izip
i = iter(a)
b = dict(izip(i, i))

In Python 3 potresti anche usare una comprensione dettata, ma ironicamente penso che il modo più semplice per farlo sarà con range()e len(), che normalmente sarebbe un odore di codice.

b = {a[i]: a[i+1] for i in range(0, len(a), 2)}

Quindi il iter()/izip()metodo è probabilmente il più Pythonic in Python 3, anche se, come nota EOL in un commento, zip()è già pigro in Python 3, quindi non è necessario izip().

i = iter(a)
b = dict(zip(i, i))

Se lo vuoi su una riga, dovrai imbrogliare e utilizzare un punto e virgola. ;-)


9
... o semplicemente zip(i, i), in Python 3, da zip()allora restituisce un iteratore.
Eric O Lebigot il

5
Nota che Python 2.7.3 ha anche una comprensione
dettata dall'utente

56

Semplice risposta

Un'altra opzione (per gentile concessione di Alex Martelli - fonte ):

dict(x[i:i+2] for i in range(0, len(x), 2))

Nota correlata

Se hai questo:

a = ['bi','double','duo','two']

e vuoi questo (ogni elemento della lista digita un dato valore (2 in questo caso)):

{'bi':2,'double':2,'duo':2,'two':2}

Puoi usare:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}

2
È solo per Python 3?
Tagar,

2
usare fromkeys. >>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2}
Gdogg,

1
Questo sta facendo qualcosa di diverso da quello che la domanda sta ponendo.
ozn

17

Puoi usare una comprensione del dict per questo abbastanza facilmente:

a = ['hello','world','1','2']

my_dict = {item : a[index+1] for index, item in enumerate(a) if index % 2 == 0}

Ciò equivale al ciclo for di seguito:

my_dict = {}
for index, item in enumerate(a):
    if index % 2 == 0:
        my_dict[item] = a[index+1]

10

Qualcosa che trovo piuttosto interessante, che è che se la tua lista è lunga solo 2 articoli:

ls = ['a', 'b']
dict([ls])
>>> {'a':'b'}

Ricorda, dict accetta qualsiasi iterabile contenente un iterabile in cui ogni elemento nell'iterabile deve essere esso stesso iterabile con esattamente due oggetti.


rapido e semplice, solo per aggiungere se l'elenco contiene più di due elementi, utilizzare dict (ls) anziché dict ([ls]). ad esempio se ls = ['a', 'b', 'c', 'd'] quindi dict (ls)
ankit tyagi,

1
Bello ed elegante. 'ogni elemento nell'iterabile deve essere esso stesso un iterabile con esattamente due oggetti.' è il fatto chiave qui.
Abhijeet,

4

Potrebbe non essere il più pitonico, ma

>>> b = {}
>>> for i in range(0, len(a), 2):
        b[a[i]] = a[i+1]


5
enumerare non consente di specificare una dimensione del passaggio, ma è possibile utilizzare for i, key in enumerate(a[::2]):. Ancora poco sincero poiché il costruttore di dict può fare la maggior parte del lavoro qui per te
John La Rooy,

@SilentGhost, gnibbler: grazie mille per allargare i miei orizzonti! Sarò sicuro di incorporarlo il più possibile in futuro!
sahhhm,

@gnibbler: potresti spiegarci un po 'di più su come for i, key in enumerate(a[::2]):potrebbe funzionare l' approccio? I valori di coppia risultanti sarebbero 0 helloe 1 1, ed è poco chiaro per me come usarli per produrre {'hello':'world', '1':'2'}.
martineau,

1
@martineau, hai ragione. Penso di aver significatoenumerate(a)[::2]
John La Rooy il

4

Puoi farlo abbastanza velocemente senza creare array extra, quindi funzionerà anche per array molto grandi:

dict(izip(*([iter(a)]*2)))

Se hai un generatore a, ancora meglio:

dict(izip(*([a]*2)))

Ecco il riassunto:

iter(h)    #create an iterator from the array, no copies here
[]*2       #creates an array with two copies of the same iterator, the trick
izip(*())  #consumes the two iterators creating a tuple
dict()     #puts the tuples into key,value of the dictionary

questo creerà un dizionario con uguali coppie chiave e valore ( {'hello':'hello','world':'world','1':'1','2':'2'})
mik

No, tutto funziona bene. Si prega di leggere più attentamente. Dice: "Se hai un generatore un ..." Se non hai un generatore, usa solo la prima riga. La seconda è un'alternativa che sarebbe utile se si dispone di un generatore anziché di un elenco, come si farebbe il più delle volte.
topkara,

1

Puoi anche farlo in questo modo (stringa per elencare la conversione qui, quindi la conversione in un dizionario)

    string_list = """
    Hello World
    Goodbye Night
    Great Day
    Final Sunset
    """.split()

    string_list = dict(zip(string_list[::2],string_list[1::2]))

    print string_list


0

Non sono sicuro che questo sia pitonico, ma sembra funzionare

def alternate_list(a):
   return a[::2], a[1::2]

key_list,value_list = alternate_list(a)
b = dict(zip(key_list,value_list))

0

prova sotto il codice:

  >>> d2 = dict([('one',1), ('two', 2), ('three', 3)])
  >>> d2
      {'three': 3, 'two': 2, 'one': 1}

0

Puoi anche provare questo approccio salvando le chiavi e i valori in un elenco diverso e quindi utilizzare il metodo dict

data=['test1', '1', 'test2', '2', 'test3', '3', 'test4', '4']

keys=[]
values=[]
for i,j in enumerate(data):
    if i%2==0:
        keys.append(j)
    else:
        values.append(j)

print(dict(zip(keys,values)))

produzione:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}

0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

result : {'hello': 'world', '1': '2'}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.