Конвертировать два списка в словарь в Python

Представь, что у тебя есть:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

Какой самый простой способ создать следующий словарь?

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

26 ответов

Решение

Как это:

>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}

Вуаля:-) Попарно dict конструктор и zip функция очень полезна: https://docs.python.org/3/library/functions.html

Представь, что у тебя есть:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

Какой самый простой способ создать следующий словарь?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

Наиболее производительный - Python 2.7 и 3, понимание слова:

Возможным улучшением использования конструктора dict является использование собственного синтаксиса понимания dict (а не понимания списка, как его ошибочно выразили другие):

new_dict = {k: v for k, v in zip(keys, values)}

В Python 2 zip возвращает список, чтобы избежать создания ненужного списка, используйте izip вместо этого (псевдоним zip может уменьшить изменения кода при переходе на Python 3).

from itertools import izip as zip

Так что это еще:

new_dict = {k: v for k, v in zip(keys, values)}

Python 2, идеально подходит для <= 2.6

izip от itertools становится zip в Python 3. izip лучше, чем zip для Python 2 (потому что он избегает ненужного создания списка), и идеально подходит для 2.6 или ниже:

from itertools import izip
new_dict = dict(izip(keys, values))

Python 3

В Python 3 zip становится той же функцией, которая была в itertools модуль, так что это просто:

new_dict = dict(zip(keys, values))

Тем не менее, более точное понимание будет более продуктивным (см. Обзор производительности в конце этого ответа).

Результат для всех случаев:

Во всех случаях:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

Объяснение:

Если мы посмотрим на помощь по dict мы видим, что это принимает различные формы аргументов:

>>> help(dict)

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)

Оптимальным подходом является использование итерируемого, избегая при этом создания ненужных структур данных. В Python 2 zip создает ненужный список:

>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

В Python 3 эквивалент будет:

>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

и Python 3 zip просто создает повторяемый объект:

>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>

Поскольку мы хотим избежать создания ненужных структур данных, мы обычно хотим избегать Python 2 zip (так как это создает ненужный список).

Менее производительные альтернативы:

Это выражение генератора передается конструктору dict:

generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)

или эквивалентно:

dict((k, v) for k, v in zip(keys, values))

И это понимание списка, передаваемое конструктору dict:

dict([(k, v) for k, v in zip(keys, values)])

В первых двух случаях дополнительный слой неоперативных (таким образом, ненужных) вычислений помещается поверх итерируемого zip, и в случае понимания списка дополнительный список создается без необходимости. Я ожидал бы, что все они будут менее производительными, и конечно не более.

Обзор производительности:

В 64-битном Python 3.4.3 в Ubuntu 14.04 упорядочено от самого быстрого до самого медленного:

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.7836067057214677
>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
1.0321204089559615
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
1.0714934510178864
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.6110592018812895
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.7361853648908436

Попробуй это:

>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}

В Python 2 это также более экономно по сравнению с zip,

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}

Вы также можете использовать словарь в Python ≥ 2.7:

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}

Более естественным способом является использование словарного понимания

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}

Если вам нужно преобразовать ключи или значения перед созданием словаря, тогда можно использовать выражение генератора. Пример:

>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3])) 

Посмотрите код, как Pythonista: Идиоматический Python.

С Python 3.x, для понимания

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in zip(keys, values)}

print(dic)

Больше на понимании dict здесь, пример есть:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

Для тех, кто нуждается в простом коде и не знаком с zip:

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

Это можно сделать одной строкой кода:

d = {List1[n]: List2[n] for n in range(len(List1))}

Вот также пример добавления значения списка в вашем словаре

list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)

всегда проверяйте, чтобы ваш "Ключ"(list1) всегда был в первом параметре.

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}

У меня было это сомнение, когда я пытался решить проблему, связанную с графами. Проблема, с которой я столкнулся, заключалась в том, что мне нужно было определить пустой список смежности, и я хотел инициализировать все узлы пустым списком, и тогда я подумал, как насчет того, чтобы проверить, достаточно ли это быстро, то есть стоит ли выполнять операцию zip? вместо простой пары ключ-значение присваивания. Ведь в большинстве случаев фактор времени является важным ледоколом. Поэтому я выполнил операцию timeit для обоих подходов.

import timeit
def dictionary_creation(n_nodes):
    dummy_dict = dict()
    for node in range(n_nodes):
        dummy_dict[node] = []
    return dummy_dict


def dictionary_creation_1(n_nodes):
    keys = list(range(n_nodes))
    values = [[] for i in range(n_nodes)]
    graph = dict(zip(keys, values))
    return graph


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped

iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)

for trail in range(1, 8):
    print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')

Для n_nodes = 10 000 000 я получаю,

Итерация: 2.825081646999024 Сокращение: 3.535717916001886

Итерация: 5.051560923002398 Сокращение: 6.255070794999483

Итерация: 6.52859034499852 Сокращение: 8.221581164998497

Итерация: 8.683652416999394 Сокращение: 12.599181543999293

Итерация: 11.587241565001023 Сокращение: 15.27298851100204

Итерация: 14.816342867001367 Сокращение: 17.162912737003353

Итерация: 16.645022411001264 Сокращение: 19.976680120998935

После определенного момента вы можете ясно видеть, что итерационный подход на n-м шаге обгоняет время, необходимое для стенографического подхода на n-1-м шаге.

  • 2018-04-18

Лучшее решение по-прежнему:

In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...: 

In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}

Транспонировать это:

    lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
    keys, values = zip(*lst)
    In [101]: keys
    Out[101]: ('name', 'age', 'food')
    In [102]: values
    Out[102]: ('Monty', 42, 'spam')

Вы можете использовать этот код ниже:

dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))

Но убедитесь, что длина списков будет одинаковой. Если длина не одинакова. Затем функция zip перевернет длинную.

      keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
dic = {}
c = 0
for i in keys:
    dic[i] = values[c]
    c += 1

print(dic)
{'name': 'Monty', 'age': 42, 'food': 'spam'}

Все ответы суммируются:

      l = [1, 5, 8, 9]
ll = [3, 7, 10, 11]

почтовый индекс :

      dict(zip(l,ll)) # {1: 3, 5: 7, 8: 10, 9: 11}

#if you want to play with key or value @recommended

{k:v*10 for k, v in zip(l, ll)} #{1: 30, 5: 70, 8: 100, 9: 110}

счетчик :

      d = {}
c=0
for k in l:
    d[k] = ll[c] #setting up keys from the second list values
    c += 1
print(d)
{1: 3, 5: 7, 8: 10, 9: 11}

перечислить :

      d = {}
for i,k in enumerate(l):
    d[k] = ll[i]
print(d)
{1: 3, 5: 7, 8: 10, 9: 11}

В большинстве ответов здесь упоминается создание кортежей с элементом из каждого изkeysиvaluesсписки. Это работает нормально, пока списки имеют одинаковую длину. Если списки имеют разную длину, он останавливается на более коротком списке; таким образом игнорируя оставшиеся элементы в более длинном списке. Следующий пример иллюстрирует этот момент:

      keys = ['name', 'age', 'food']
values = ['Monty', 42]
dict(zip(keys, values))                    # {'name': 'Monty', 'age': 42}

В случаях, когда такое поведение нежелательно, применяется аналогичный метод.itertools.zip_longestсуществует в стандартной библиотеке, которая создает итератор, который выполняет итерацию до тех пор, пока не будет исчерпан более длинный список. По умолчанию пропущенные значения заполняются значением Нет.

      from itertools import zip_longest
dict(zip_longest(keys, values))            # {'name': 'Monty', 'age': 42, 'food': None}

Он также принимаетfillvalue=kwarg, который можно использовать для указания того, что следует заполнить вместо пропущенных значений.

      dict(zip_longest(keys, values, fillvalue='spam')) # {'name': 'Monty', 'age': 42, 'food': 'spam'}

Обратите внимание: если оба списка имеют одинаковую длину,zip()иitertools.zip_longest()выдать тот же результат:

      keys = values = range(5)
dict(zip(keys, values)) == dict(zip_longest(keys, values))                       # True
{k:v for k,v in zip(keys, values)} == {k:v for k,v in zip_longest(keys, values)} # True

Это можно сделать следующим образом.

      keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam'] 

dict = {}

for i in range(len(keys)):
    dict[keys[i]] = values[i]
    
print(dict)

{'name': 'Monty', 'age': 42, 'food': 'spam'}

Если вы работаете с более чем одним набором значений и хотите получить список диктовок, вы можете использовать это:

      def as_dict_list(data: list, columns: list):
    return [dict((zip(columns, row))) for row in data]

Пример из реальной жизни - это список кортежей из запроса базы данных в паре с кортежем столбцов из того же запроса. Остальные ответы предоставлены только 1 к 1.

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
new_dict = dict(zip(keys,values))
print(new_dict)
      import pprint

p = ['A', 'B', 'C']
q = [5, 2, 7]
r = ["M", "F", "M"]
s = ['Sovabazaar','Shyambazaar','Bagbazaar','Hatkhola']


def makeDictUsingAlternateLists1(**rest):
    print("*rest.keys() : ",*rest.keys())
    print("rest.keys() : ",rest.keys())
    print("*rest.values() : ",*rest.values())
    print("**rest.keys() : ",rest.keys())
    print("**rest.values() : ",rest.values())
    [print(a) for a in zip(*rest.values())]
    
    [ print(dict(zip(rest.keys(),a))) for a in zip(*rest.values())]
    print("...")
    
    
    finalRes= [ dict( zip( rest.keys(),a))  for a in zip(*rest.values())] 
    return finalRes
    
l = makeDictUsingAlternateLists1(p=p,q=q,r=r,s=s)
pprint.pprint(l)    
"""
*rest.keys() :  p q r s
rest.keys() :  dict_keys(['p', 'q', 'r', 's'])
*rest.values() :  ['A', 'B', 'C'] [5, 2, 7] ['M', 'F', 'M'] ['Sovabazaar', 'Shyambazaar', 'Bagbazaar', 'Hatkhola']
**rest.keys() :  dict_keys(['p', 'q', 'r', 's'])
**rest.values() :  dict_values([['A', 'B', 'C'], [5, 2, 7], ['M', 'F', 'M'], ['Sovabazaar', 'Shyambazaar', 'Bagbazaar', 'Hatkhola']])
('A', 5, 'M', 'Sovabazaar')
('B', 2, 'F', 'Shyambazaar')
('C', 7, 'M', 'Bagbazaar')
{'p': 'A', 'q': 5, 'r': 'M', 's': 'Sovabazaar'}
{'p': 'B', 'q': 2, 'r': 'F', 's': 'Shyambazaar'}
{'p': 'C', 'q': 7, 'r': 'M', 's': 'Bagbazaar'}
...
[{'p': 'A', 'q': 5, 'r': 'M', 's': 'Sovabazaar'},
 {'p': 'B', 'q': 2, 'r': 'F', 's': 'Shyambazaar'},
 {'p': 'C', 'q': 7, 'r': 'M', 's': 'Bagbazaar'}]
 
"""

Вы можете сделать это одной строкой, используя словарь:

a_dict={key:value for key,value in zip(keys,values)}

и это все. Наслаждайтесь Python.....;)

Решение как понимание словаря с enumerate:

dict = {item : values[index] for index, item in enumerate(keys)}

Решение как для цикла с перечислением:

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]

Хотя есть несколько способов сделать это, но я считаю наиболее фундаментальным подходом к этому; создание цикла и словаря и сохранение значений в этом словаре. В рекурсивном подходе идея все та же, но вместо использования цикла функция вызывала сама себя, пока не дойдет до конца. Конечно, есть и другие подходы, например, использованиеdict(zip(key, value))и т.д. Это не самые эффективные решения.

y = [1,2,3,4]
x = ["a","b","c","d"]

# This below is a brute force method
obj = {}
for i in range(len(y)):
    obj[y[i]] = x[i]
print(obj)

# Recursive approach 
obj = {}
def map_two_lists(a,b,j=0):
    if j < len(a):
        obj[b[j]] = a[j]
        j +=1
        map_two_lists(a, b, j)
        return obj
      


res = map_two_lists(x,y)
print(res)

Оба результата должны напечатать

{1: 'a', 2: 'b', 3: 'c', 4: 'd'}  

Вы также можете попробовать один список, который представляет собой комбинацию двух списков;)

a = [1,2,3,4]
n = [5,6,7,8]

x = []
for i in a,n:
    x.append(i)

print(dict(zip(x[0], x[1])))

Метод без функции почтового индекса

l1 = {1,2,3,4,5}
l2 = {'a','b','c','d','e'}
d1 = {}
for l1_ in l1:
    for l2_ in l2:
        d1[l1_] = l2_
        l2.remove(l2_)
        break  

print (d1)


{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
index=np.arange(0,len(keys)-1)

df=pd.DataFrame(list(zip(keys,values)), columns=['keys','values'])
df.set_index('keys')
print(df.head())

data_dict = df.iloc[index].set_index('keys')['values'].to_dict() 
print(data_dict)

zip создает генератор параллельных значений. list() создает экземпляр полного генератора и передает его в фрейм данных, который преобразует все выражение. результирующий вывод:

два списка:

    keys values
 0  name  Monty
 1   age     42
 2  food   spam
 

Выход: словарь

 {'name': 'Monty', 'age': 42}
Другие вопросы по тегам