17

Создание словаря (dict) из отдельных списков ключей и значений

13

Я пытаюсь объединить два списка в один словарь. У меня есть следующие данные:

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

Я хотел бы получить результат в виде:

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

Как я могу это сделать?

5 ответ(ов)

2

Самый простой способ создать словарь на основе ваших ключей и значений — использовать конструктор dict с функцией zip. Вот пример:

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

В Python 3 функция zip теперь возвращает «ленивый» итератор, что делает этот подход наиболее производительным. dict(zip(keys, values)) требует единовременной глобальной проверки для dict и zip, но при этом не создает ненужных промежуточных структур данных и не требует локальных проверок при применении функции.

Альтернатива — генератор словаря

Близким по производительности вариантом будет использование синтаксиса генератора словаря (не путать с генератором списка):

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

Этот способ стоит использовать, если вам необходимо преобразовать или отфильтровать данные на основе ключей или значений.

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

from itertools import izip as zip
new_dict = {k: v for k, v in zip(keys, values)}

Для Python 2, для версий ⇐ 2.6

Функция izip из модуля itertools в Python 3 становится обычной zip. Она лучше, чем zip в Python 2, так как не создает лишний список.

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

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

В любом случае вы получите:

>>> new_dict
{'name': 'Monty', 'age': 42, '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')]

Тем не менее, zip в Python 3 просто создает итератор:

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

Поскольку мы хотим избежать создания ненужных структур данных, обычно мы предпочитаем zip в Python 3, а не 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([(k, v) for k, v in zip(keys, values)])

В первых двух случаях создает дополнительный уровень ненужных вычислений, а в последнем — лишний список. Все эти варианты, скорее всего, будут менее производительными, чем использование dict(zip(keys, values)).

Анализ производительности:

В Python 3.8.2, оценив производительность различных методов, можно сделать выводы:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583

dict(zip(keys, values)) показывает лучшие результаты даже с небольшими объемами данных, а с увеличением объемов производительность будет различаться еще больше.

Не стоит забывать, что использование min для выбора производительности — это нормальная практика в анализе алгоритмов, так как мы хотим узнать производительность в наилучших условиях.

1

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

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

0

В вашем коде вы создаете словарь, используя функцию zip, которая принимает два итерируемых объекта — в данном случае, кортежи keys и values.

Вот пошаговое объяснение:

  1. keys — это кортеж, содержащий строки, которые будут использоваться в качестве ключей: ('name', 'age', 'food').
  2. values — это тоже кортеж, содержащий значения для соответствующих ключей: ('Monty', 42, 'spam').
  3. Функция zip(keys, values) объединяет элементы из обоих кортежей в пары, создавая итератор, в котором каждый элемент — это кортеж, содержащий ключ и значение. То есть, получится такой итератор: (('name', 'Monty'), ('age', 42), ('food', 'spam')).
  4. Затем dict() создает словарь из этих пар.

В результате создается словарь, который будет выглядеть следующим образом:

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

Обратите внимание, что порядок ключей в словаре, как правило, не гарантируется, но с Python 3.7 и выше порядок сохранится как в исходных данных.

0

Вы также можете использовать выражения-генераторы для словарей в 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'}

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

0

Более естественный способ — это использовать генератор словарей:

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

В данном коде мы создаем словарь result_dict, где ключи берутся из кортежа keys, а значения — из кортежа values. Использование генератора словаря позволяет сделать код более читаемым и избежать необходимости использования других конструкций, таких как цикл. Вместо этого можно использовать функцию zip() для более краткой записи:

result_dict = dict(zip(keys, values))

Этот способ ещё более лаконичен и делает код чище.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь