Советы по более элегантному коду для создания словаря - PullRequest
3 голосов
/ 10 мая 2019

Я создаю словарь с ключами и значениями из списков:

keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

Я могу вручную создать словарь следующим образом:

dictionary = {'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Как создать более элегантнодиктат из списков по циклу?Моя проблема в том, что размер списков намного больше, чем в этом примере.

Ответы [ 3 ]

9 голосов
/ 10 мая 2019

Посмотрите на zip:

>>> d = dict(zip(keys, val))
>>> d
{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Создайте итератор, который агрегирует элементы из каждого из итераций.

Возвращает итераториз кортежей, где i-й кортеж содержит i-й элемент из каждой последовательности аргументов или итераций.

Затем мы передаем возвращаемое значение в dict, чтобы создать словарь.Это, вероятно, более эффективно, чем простой цикл, поскольку встроенные модули работают на скорости C внутри Python, и у разработчиков, вероятно, было больше времени для его оптимизации.

6 голосов
/ 10 мая 2019

Используйте словарь, в котором вы выбираете ключ и значение из списка keys и val при их итерации по ним, и просто для безопасности, если keys и val имеют неодинаковую длинуВы можете сжать их все вместе с помощью itertools.zip_longest , который создаст итератор самой длинной подпоследовательности, убедившись, что если, скажем, keys длиннее val, у нас нет ключей для них,может быть, переназначить их в будущем (Спасибо @quamrana)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})

Вывод

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Пример большей длины keys, чем val

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})

Вывод будет

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 
'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first', 
'QX': None, 'QY': None}

, поэтому мы видим, что ключи здесь не потеряны, а используются и значения установлены на None, но использование zip приведет к потереэти ключи!

Но если мы хотим выбрать только элементы из меньшего списка, мы можем сделать следующее (спасибо @MitchelPaulin)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

#Pick the smaller of the 2 lengths and iterate only on those indexes
length = min(len(keys), len(val))
print({keys[idx]:val[idx] for idx in range(length)})
0 голосов
/ 10 мая 2019

Этот подход использует zip с простым добавлением второго списка, чтобы соответствовать размерам.

l1=['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'Q4' ]
l2=['max', 'first' ]

# make sure we have the same length
for i in range (len(l1)-len(l2)): l2.append(None)

d={}
d={k:v for k,v in zip(l1,l2)}
print(d)

Обратите внимание, что я использовал append(None) как zip_longest использует fillvalue=None.


{'Ptot': 'max', 'P1': 'first', 'P2': None, 'P3': None, 'Q1': None, 'Q2': None, 'Q3': None, 'Q4': None}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...