Преобразовать список в словарь в Python


191

Допустим, у меня есть список aв Python, чьи записи удобно отображаются в словарь. Каждый четный элемент представляет ключ к словарю, а следующий нечетный элемент является значением

например,

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

и я хотел бы преобразовать его в словарь b, где

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

Какой синтаксически самый чистый способ сделать это?


Ответы:


272
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}

Это эквивалентно циклу for ниже:

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 tyagi

1
Красиво и гладко. «Каждый элемент в итерируемом должен быть итерируемым ровно с двумя объектами». это ключевой факт здесь.
Абхиджит

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]
Джон La Rooy

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

Нет, все работает просто отлично. Пожалуйста, прочитайте более внимательно. Там написано: «Если у вас есть генератор ...» Если у вас нет генератора, просто используйте первую строку. Второй вариант - это альтернатива, которая будет полезна, если у вас есть генератор вместо списка, как это было бы в большинстве случаев.
Топкара

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.