Перетворіть список у словник на Python


190

Скажімо, у мене є список aв Python, записи якого зручно відображати до словника. Кожен парний елемент являє собою ключ до словника, а наступний непарний елемент - значення

наприклад,

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

і я хотів би перетворити його у словник b , куди

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

Який синтаксично найчистіший спосіб досягти цього?


3
Можливий дублікат Make словника зі списку з python
Jeru Luke

Відповіді:


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

Якщо aвона велика, ви, ймовірно, захочете зробити щось на кшталт наступного, що не робить жодних тимчасових списків, як описано вище.

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

У Python 3 ви також можете використовувати розуміння диктанту, але, як не дивно, я думаю, що найпростіший спосіб зробити це буде з, range()і це len(), як правило, запах коду.

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

Таким чином, iter()/izip()метод, мабуть, є найбільш Pythonic в Python 3, хоча, як зазначає EOL у коментарі, zip()у Python 3 вже ледачий, тому вам не потрібно izip().

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

Якщо ви хочете, щоб це було в одному рядку, вам доведеться обдурити і використовувати крапку з комою. ;-)


9
… Або просто zip(i, i)в Python 3, оскільки zip()тепер повертає ітератор.
Ерік О Лебігот

5
Зауважте, що Python 2.7.3 також має розуміння
дикту

56

Проста відповідь

Ще один варіант (люб’язно надано Алексі Мартеллі - джерело ):

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

Пов’язана примітка

Якщо у вас є це:

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

і ви хочете цього (кожен елемент списку вводить задане значення (2 у цьому випадку)):

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

Ви можете використовувати:

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

2
Це лише для Python 3?
Тагар

2
використання fromkeys. >>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2}
Gdogg

1
Це щось інше, ніж те, що задається питанням.
ozn

17

Ви можете використовувати розуміння дакту для цього досить легко:

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

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

Це еквівалентно циклу для циклу нижче:

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

10

Щось мені здається досить крутим, а це те, що якщо у вашому списку лише 2 пункти:

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

Пам'ятайте, що dict приймає будь-який ітерабельний вміст, який містить ітерабельний файл, де кожен елемент в ітерабелі повинен бути ітерабельним з точно двома об'єктами.


швидкий і простий, просто додати, якщо список містить більше двох елементів, тоді використовуйте dict (ls) замість dict ([ls]). наприклад, якщо ls = ['a', 'b', 'c', 'd'], то dict (ls)
ankit tiagi

1
Приємно і гладко. "кожен елемент в ітерабелі повинен бути самим ітерабельним з точно двома об'єктами." тут є ключовим фактом.
Abhijeet

4

Не може бути найпітонічнішим, але

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

10
читати проenumerate
SilentGhost

5
перерахування не дозволяє вказати розмір кроку, але ви можете використовувати for i, key in enumerate(a[::2]):. Досі нетиповий, оскільки конструктор dict може зробити для вас більшу частину роботи
Джон Ла Рой

@SilentGhost, gnibbler: велике спасибі за розширення мого кругозору! Я обов'язково включу його якомога більше в майбутньому!
sahhhm

@gnibbler: Чи можете ви пояснити трохи більше про те, як for i, key in enumerate(a[::2]):може працювати підхід? Отримані в результаті пари значення були б 0 helloі 1 1мені незрозуміло, як їх використовувати для отримання {'hello':'world', '1':'2'}.
мартіно

1
@martineau, ти прав. Я думаю, я мав на увазіenumerate(a)[::2]
Джон Ла Рой

4

Ви можете зробити це досить швидко, не створюючи зайвих масивів, так що це буде працювати навіть для дуже великих масивів:

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

Якщо у вас є генератор a, ще краще:

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

Ось такий пробіг:

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

це зробить словник з рівними парами ключів і значень ( {'hello':'hello','world':'world','1':'1','2':'2'})
mik

Ні, всі працюють просто чудово. Прочитайте уважніше. Там написано: "Якщо у вас є генератор ..." Якщо у вас немає генератора, просто використовуйте перший рядок. Другий варіант - це альтернатива, яка була б корисною, якщо у вас замість списку є генератор, як це було б більшість часу.
topkara

1

Ви також можете зробити це так (рядок, щоб перерахувати перетворення тут, потім перехід у словник)

    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

1

Мені також дуже цікаво мати однолінійний перехід для цієї конверсії, наскільки такий список є ініціалізатором за замовчуванням для хешованих в Perl.

Надзвичайно вичерпна відповідь дана в цій темі -

Один мій Я новачок в Python), використовуючи вирази генератора Python 2.7 , буде:

dict((a[i], a[i + 1]) for i in range(0, len(a) - 1, 2))


0

Я не впевнений, чи це пітонічно, але, здається, працює

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

спробуйте нижче код:

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

0

Ви також можете спробувати цей підхід зберегти ключі та значення в іншому списку, а потім використовувати метод 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)))

вихід:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.