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

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

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

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
1176
Guido 16 Окт 2008 в 23:05

15 ответов

Лучший ответ

Нравится:

>>> 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#func-dict

2051
Dan Lenski 23 Янв 2020 в 14:44

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

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

Посмотрите код, похожий на Pythonista: идиоматический Python.

13
jfs 16 Окт 2008 в 20:45

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

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

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

2
Akash Nayak 16 Ноя 2017 в 13:36

Решение как словарь с перечислением:

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

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

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]
0
Georgy 5 Ноя 2019 в 08:42
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}
33
iny 16 Окт 2008 в 19:09

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

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]}
1
Cyd 20 Фев 2019 в 12:25

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

>>> 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.

127
Jean-François Fabre 13 Сен 2017 в 11:48

Вы также можете использовать словарь в 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'}
28
Brendan Berg 10 Июн 2012 в 20:03

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

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'}
-1
Nursnaaz 31 Янв 2019 в 08:54
  • 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')
3
Calculus 18 Апр 2018 в 02:41

С Python 3.x, идет на понимание dict

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

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

print(dic)

Подробнее о толковании здесь, например:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
10
kiriloff 25 Май 2013 в 13:47

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

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}
15
Polla A. Fattah 13 Апр 2016 в 02:07

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

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

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

d = {List1[n]: List2[n] for n in range(len(List1))}
8
Ry- 28 Апр 2013 в 15:18

У меня было это сомнение, когда я пытался решить проблему, связанную с графами. Проблема, с которой я столкнулся, заключалась в том, что мне нужно было определить пустой список смежности, и я хотел инициализировать все узлы пустым списком, и тогда я подумал, как насчет того, чтобы проверить, достаточно ли это быстро, то есть, стоит ли выполнять операцию 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-м шаге.

2
Mayank Prakash 20 Июл 2019 в 10:01

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

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>

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

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

Это выражение генератора передается конструктору 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.7.3 в Ubuntu 18.04 упорядочено от самого быстрого до самого медленного:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.4772876740025822
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.5217149950040039
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.6797661719901953
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
0.7864680950006004
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
0.8561034000013024

Комментатор сказал:

min кажется плохим способом сравнения производительности. Конечно, mean и / или max были бы гораздо более полезными индикаторами для реального использования.

Мы используем min, потому что эти алгоритмы являются детерминированными. Мы хотим знать производительность алгоритмов в наилучших возможных условиях.

Если операционная система по какой-либо причине зависает, это не имеет ничего общего с тем, что мы пытаемся сравнить, поэтому мы должны исключить такие результаты из нашего анализа.

Если бы мы использовали mean, события такого рода сильно исказили бы наши результаты, и если бы мы использовали max, мы получим только самый экстремальный результат - тот, который наиболее вероятно затронут таким событием.

Комментатор также говорит:

В Python 3.6.8, используя средние значения, понимание dict действительно еще быстрее, примерно на 30% для этих небольших списков. Для больших списков (10 000 случайных чисел) вызов dict выполняется примерно на 10% быстрее.

Я предполагаю, что мы имеем в виду dict(zip(... с 10k случайных чисел. Это звучит как довольно необычный вариант использования. Имеет смысл, что большинство прямых вызовов будут доминировать в больших наборах данных, и я не удивлюсь, если зависания ОС будут доминирующими, учитывая, сколько времени потребуется для запуска этого теста, что приведет к дальнейшему искажению ваших номеров. И если вы используете mean или max, я бы посчитал ваши результаты бессмысленными.

Давайте использовать более реалистичный размер в наших лучших примерах:

import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))

И мы видим здесь, что dict(zip(... действительно работает быстрее для больших наборов данных примерно на 20%.

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095
133
Aaron Hall 3 Окт 2019 в 13:25