Відповіді:
Подобається це:
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
Voila :-) dict
Конструктор і zip
функція попарно надзвичайно корисні: https://docs.python.org/3/library/functions.html#func-dict
{thing}
- синтаксичний цукор для побудови set()
одного елемента. {*iterable}
є синтаксичним цукром для побудови, що set
містить кілька елементів. {k:v}
або {**mapping}
буде побудувати dict
, але це синтаксичний зовсім по-різному.
{}
для словників. Фактично, якщо ми спробуємо type({})
результат є dict
. Але дійсно, якщо ми спробуємо, type({thing})
то результат є set
.
{k:v for k, v in zip(keys, values)}
. Виявляється, можемо. +1.
Уявіть, що у вас є:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Який найпростіший спосіб скласти наступний словник?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
конструктор сzip
new_dict = dict(zip(keys, values))
У Python 3 тепер zip повертає ледачий ітератор, і це зараз найефективніший підхід.
dict(zip(keys, values))
вимагає глобального пошуку в одноразовому кожен для dict
і zip
, але вона не утворює ніяких непотрібні проміжні дані-структур або мати справу з місцевими пошуками в застосуванні функції.
Ближче до використання конструктора 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
Отже, це все ще (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
from itertools
стає zip
в Python 3. izip
краще, ніж zip для Python 2 (тому що це дозволяє уникнути зайвого створення списку), і ідеально підходить для 2.6 або нижче:
from itertools import izip
new_dict = dict(izip(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.8.2, наданому Nix, на Ubuntu 16.04 впорядковано від найшвидшого до найповільнішого:
>>> 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
здається поганим способом порівняння продуктивності. Напевноmean
та / абоmax
були б набагато корисніші показники для реального використання.
Ми використовуємо, min
оскільки ці алгоритми детерміновані. Ми хочемо знати ефективність роботи алгоритмів за найкращих можливих умов.
Якщо операційна система з будь-якої причини висить, вона не має нічого спільного з тим, що ми намагаємося порівняти, тому нам потрібно виключити такі результати з нашого аналізу.
Якби ми використовували mean
, такі види подій сильно перекосили б наші результати, а якщо ми використали, max
то отримаємо лише найекстремальніший результат - той, який найбільше постраждав від такої події.
Також коментатор говорить:
У python 3.6.8, використовуючи середні значення, розуміння дикту дійсно все ж швидше, приблизно на 30% для цих невеликих списків. Для більш великих списків (10 к випадкових чисел)
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
dict(zip(headList, textList))
& 1,95 \ pm 0,030 microsec for {k: v for k, v in zip(headList, textList)}
. Я б запропонував попереднього для читабельності та швидкості. Очевидно, що це отримується в аргументі min () vs mean () для timeit.
min
здається поганим способом порівняння продуктивності. Напевно mean
та / або max
були б набагато корисніші показники для реального використання.
dict
дзвінок приблизно на 10% швидше.
Спробуйте це:
>>> 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
.
zip
вже економічно витрачено на пам'ять. docs.python.org/3/library/functions.html#zip Насправді, ви можете бачити , що six
використання zip
в Python 3 для заміни itertools.izip
в Python 2 pythonhosted.org/six .
Ви також можете використовувати розуміння словника на 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))}
dict
об’єкт, чому це так ?, дякую чувак.
Якщо вам потрібно перетворити ключі або значення перед створенням словника, тоді може бути використаний вираз генератора . Приклад:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Погляньте на кодекс як на Pythonista: Idiomatic Python .
з Python 3.x, використовується для розуміння диктату
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'}
Для тих, хто потребує простого коду і не знайомий з zip
:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
Це можна зробити за допомогою одного рядка коду:
d = {List1[n]: List2[n] for n in range(len(List1))}
List1
довшеList2
for n in range(len(List1))
є анти-візерунок
Найкращим рішенням все ж є:
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')
У мене виникли такі сумніви, коли я намагався вирішити проблему, пов'язану з графіком. У мене виникло питання, що мені потрібно було визначити порожній список суміжності, і я хотів ініціалізувати всі вузли з порожнім списком, саме тоді я подумав, як перевірити, чи досить швидко він, я маю на увазі, чи варто робити операцію zip а не просте присвоєння пари ключ-значення. Зрештою, більшість випадків фактор часу є важливим криголам. Тому я провів операцію часу для обох підходів.
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_-му кроці.
Ось також приклад додавання значення списку у вашому словнику
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]}
Ви також можете спробувати один список, який є комбінацією двох списків;)
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])))
метод без функції zip
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'}
dictionary = {zip(keys, values)}
не вийде. Ви повинні прямо заявити якdict(...)