как назначить список значений ключу с помощью OrderedDict в python
привет хочу иметь упорядоченный словарь с ключами, имеющими список значений.
снизу кода я мог бы получить словарь со списком ключей, но порядок вставки отсутствует.
from collections import defaultdict
keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = defaultdict(list)
i=0
for key in keys:
dic[key].append(vals1[i])
dic[key].append(vals2[i])
i += 1
print dic
Я получаю следующий результат
defaultdict(<type 'list'>, {'pri': ['primary', 'S2'], 'ani': ['anim', 'S3'], 'blk': ['blocking', 'S1']})
здесь я потерял порядок вставки.
Я знаю, что объект defaultdict в Python неупорядочены по определению.
и я знаю, что нужно использовать OrderedDict если вам нужно порядок, в котором были вставлены значения (он доступен в Python 2.7 и 3.x)
так изменил мой код, как показано ниже
снизу кода я мог бы получить то, что мне нужно.
from collections import defaultdict,OrderedDict
keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = OrderedDict(defaultdict(list))
i=0
for key in keys:
dic[key].append(vals1[i])
dic[key].append(vals2[i])
i += 1
print dic
и теперь я получаю следующую ошибку
Traceback (most recent call last):
File "Dict.py", line 18, in <module>
dic[key].append(vals1[i])
KeyError: 'blk'
может кто-нибудь сказать мне, как получить то, что я пытаюсь.
3 ответов
если вы действительно хотите "заказал" и поведение "по умолчанию", я думаю, я бы создал пользовательский класс словаря для обработки всего для меня:
from collections import OrderedDict
class DefaultListOrderedDict(OrderedDict):
def __missing__(self,k):
self[k] = []
return self[k]
keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = DefaultListOrderedDict()
for i,key in enumerate(keys):
dic[key].append(vals1[i])
dic[key].append(vals2[i])
print dic
это будет вести себя больше как defaultdict
чем другие решения, но он сохранит порядок, и это действительно не так много кода :). Наконец, вы даже можете переопределить __init__
чтобы позволить пользователю пройти любую "фабрику", которую они хотели (а не жесткое кодирование list
). Я оставлю это в качестве упражнения для заинтересованный читатель. Python такой классный.
проблема с переносом OrderedDict
вокруг defaultdict(list)
это то, что он оценивается таким образом:
- создать пустой экземпляр
defaultdict
. - создать экземпляр
OrderedDict
, затем инициализируйте его содержимымdefaultdict
(пуст), потом выкинуть староеdefaultdict
потому что ничто больше не ссылается на него.
это не сочетает в себе их поведение, как вы хотели.
стандартная идиома, которую я видел, это dict.setdefault
метод.
from collections import OrderedDict
keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
dic = OrderedDict()
i=0
for key in keys:
dic.setdefault(key, []).append(vals1[i])
dic.setdefault(key, []).append(vals2[i])
i += 1
print dic
как defaultdict, это создает значение при первом доступе к нему, хотя я понимаю, что это немного менее эффективно.
Я бы использовал этот подход, хотя:
from collections import OrderedDict
dic = OrderedDict(zip(keys, zip(vals1, vals2)))
print dic
попробуйте это:
from collections import OrderedDict
keys=['blk','pri','ani']
vals1=['blocking','primary','anim']
vals2=['S1','S2','S3']
print OrderedDict(zip(keys, zip(vals1, vals2)))