Как преобразовать два списка в словарь?
Представьте, что у вас есть:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Как проще всего создать следующий словарь?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
Самый производительный конструктор
dict
сzip
new_dict = dict(zip(keys, values))
В ilist Python 3 zip теперь возвращает list ленивый итератор, и теперь data-type-conversion это наиболее эффективный ilist подход.
dict(zip(keys, values))
действительно требует dict единовременного глобального lists поиска дляdict
иzip
, но он не ilist формирует ненужных промежуточных list структур данных и не должен python иметь дело с локальным поиском py в приложении-функции.Второе место, понимание слов:
Близким dictionaries к использованию конструктора pythonic dict является использование python-shell собственного синтаксиса понимания type-conversion dict (а не понимания list, как type-conversion другие ошибочно выразились):
new_dict = {k: v for k, v in zip(keys, values)}
Выберите dict этот вариант, если вам нужно ilist сопоставить или отфильтровать python-list на основе ключей или значений.
В python-shell Python 2
zip
возвращает список, чтобы map избежать создания ненужного data-type-conversion списка, используйте вместо lists негоizip
(псевдоним zip может lists уменьшить количество изменений python кода при переходе на Python python 3).from itertools import izip as zip
Итак, это все еще (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
Python 2, идеально подходит для <= 2.6
izip
из pythonicitertools
становитсяzip
в Python 3.izip
лучше, чем dict zip для Python 2 (поскольку python-list он позволяет избежать ненужного dict создания списка), и идеально dict подходит для версии 2.6 или lists ниже:from itertools import izip new_dict = dict(izip(keys, values))
Результат для всех случаев:
Во всех случаях:
>>> new_dict {'age': 42, 'name': 'Monty', 'food': 'spam'}
Пояснение:
Если python-list мы посмотрим на справку по pythonic
dict
, мы увидим, что она принимает dictionary различные формы аргументов:>>> 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)
Оптимальный type-conversion подход - использовать итерацию, избегая dict при этом создания ненужных pythonic структур данных. В Python typeconverting 2 zip создает ненужный список:
>>> zip(keys, values) [('name', 'Monty'), ('age', 42), ('food', 'spam')]
В typeconverting Python 3 эквивалент будет:
>>> list(zip(keys, values)) [('name', 'Monty'), ('age', 42), ('food', 'spam')]
и map Python 3
zip
просто создают lists повторяемый объект:>>> zip(keys, values)
Поскольку dictionary мы хотим избежать создания list ненужных структур данных, мы python обычно не хотим использовать dictionary
zip
в Python 2 (поскольку он ilist создает ненужный список).Менее эффективные альтернативы:
Это dictionary выражение генератора, передаваемое typeconverting конструктору 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))
И type-conversion это понимание списка передается ilist конструктору dict:
dict([(k, v) for k, v in zip(keys, values)])
В первых dict двух случаях дополнительный py уровень неработающих (а значит, ненужных) вычислений list помещается поверх итерации type-conversion zip, а в случае понимания map списка без необходимости python создается дополнительный python-shell список. Я ожидал, что все type-conversion они будут менее производительными, и type-conversion уж точно не более эффективными.
Обзор производительности:
В list 64-битном Python 3.8.2, предоставляемом dictionaries Nix, в Ubuntu 16.04 в порядке lists от самого быстрого к самому dictionaries медленному:
>>> 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))
выигрывает даже pythonic с небольшими наборами ключей ilist и значений, но для больших python наборов разница в производительности py станет больше.Комментатор dictionary сказал:
min
кажется плохим способом python-list сравнения производительности. Конечно,mean
и lists / илиmax
были бы гораздо более python-list полезными индикаторами для pythonic реального использования.Мы type-conversion используем
min
, потому что эти dict алгоритмы детерминированы. Мы python-list хотим знать производительность pythonic алгоритмов в наилучших возможных dictionary условиях.Если операционная python-shell система зависает по какой-либо typeconverting причине, это не имеет никакого dictionary отношения к тому, что мы data-type-conversion пытаемся сравнить, поэтому dictionary нам нужно исключить такие dictionaries результаты из нашего анализа.
Если dictionary бы мы использовали
mean
, такие typeconverting события сильно исказили бы dictionary наши результаты, а если бы python-list мы использовалиmax
, мы получили typeconverting бы только самый экстремальный ilist результат - тот, на который, скорее lists всего, повлияет такое событие.Комментатор pythonic также говорит:
В python 3.6.8 list при использовании средних data-type-conversion значений понимание словаря ilist действительно происходит list быстрее, примерно на 30% для type-conversion этих небольших списков. Для pythonic больших списков (10k случайных python-list чисел) вызов
dict
выполняется dictionaries примерно на 10% быстрее.Я py полагаю, мы имеем в виду python-shell
dict(zip(...
с 10 тысячами случайных typeconverting чисел. Звучит как довольно type-conversion необычный вариант использования. Имеет type-conversion смысл, что самые прямые вызовы lists будут доминировать в больших ilist наборах данных, и я не удивлюсь, если data-type-conversion зависания ОС будут доминировать, учитывая, сколько python-shell времени потребуется для запуска type-conversion этого теста, что еще больше python-list искажает ваши цифры. И если lists вы используетеmean
илиmax
, я считаю python-shell ваши результаты бессмысленными.Давайте py использовать более реалистичный typeconverting размер в наших лучших примерах:
import numpy import timeit l1 = list(numpy.random.random(100)) l2 = list(numpy.random.random(100))
И dictionaries здесь мы видим, что
dict(zip(...
действительно dictionary работает быстрее для больших map наборов данных примерно на python-list 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
python
list
dictionary
type-conversion
Как преобразовать два списка в словарь?
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.