Сортировка словаря по словарям по значению
У меня есть этот словарь:
statuses = {
'pending' : {'status_for':'all', 'position':1},
'cancelled' : {'status_for':'all','position':2},
'approved' : {'status_for':'owner', 'position':1},
'rejected - owner' : {'status_for':'owner', 'position':2},
'accepted' : {'status_for':'dev', 'position':1},
'rejected - developer' : {'status_for':'dev', 'position':3},
'closed' : {'status_for':'dev', 'position':5},
}
У меня также есть функция, чтобы вытащить все значения status_for
либо owner
, либо dev
, которые выглядят так и помещают их в PyQt QComboBox:
for s in statuses:
if statuses[s]['status_for'] == "dev" or statuses[s]['status_for'] == "all":
cb_developer_status.addItem(s.capitalize(), s)
Я хотел бы заказать их по значению position
. Каков хороший способ сделать это, так что, когда я заполняю combobox, у меня есть это в предопределенном порядке?
Я понимаю, что вышеприведенный фрагмент проверяет как "dev", так и "all", мое предположение прямо сейчас состоит в том, что мне пришлось бы дважды прокручивать словарь, чтобы получить два отдельных блока в желаемом порядке (т.е. "все" появляется перед "dev" ).
Я видел этот пост, но я не уверен, как преобразовать этот ответ в нечто, что
это словарь словарей.
Ответы
Ответ 1
Что-то вроде этой работы? Подобно сообщению, которое вы связали, для функции пользовательского порядка сортировки используется key
функция sorted
. iteritems()
возвращает кортеж (key, value)
, поэтому он передается в lambda (x, y): y['position']
, где y['position']
- это значение (ваш вложенный словарь, введенный по статусу), а position
- это элемент, по которому вы хотите сортировать.
In [35]: statuses = {
'pending' : {'status_for':'all', 'position':1},
'cancelled' : {'status_for':'all','position':2},
'approved' : {'status_for':'owner', 'position':1},
'rejected - owner' : {'status_for':'owner', 'position':2},
'accepted' : {'status_for':'dev', 'position':1},
'rejected - developer' : {'status_for':'dev', 'position':3},
'closed' : {'status_for':'dev', 'position':5},
}
In [44]: for s in sorted(statuses.iteritems(), key=lambda (x, y): y['position']):
....: print s
....:
....:
('accepted', {'position': 1, 'status_for': 'dev'})
('approved', {'position': 1, 'status_for': 'owner'})
('pending', {'position': 1, 'status_for': 'all'})
('rejected - owner', {'position': 2, 'status_for': 'owner'})
('cancelled', {'position': 2, 'status_for': 'all'})
('rejected - developer', {'position': 3, 'status_for': 'dev'})
('closed', {'position': 5, 'status_for': 'dev'})
Ответ 2
In [232]: statuses = {
'pending' : {'status_for':'all', 'position':1},
'cancelled' : {'status_for':'all','position':2},
'approved' : {'status_for':'owner', 'position':1},
'rejected - owner' : {'status_for':'owner', 'position':2},
'accepted' : {'status_for':'dev', 'position':1},
'rejected - developer' : {'status_for':'dev', 'position':3},
'closed' : {'status_for':'dev', 'position':5},
}
In [235]: sorted(statuses,key=lambda x:statuses[x]['position'])
Out[235]:
['accepted',
'approved',
'pending',
'rejected - owner',
'cancelled',
'rejected - developer',
'closed']
или используя operator.getitem()
:
In [260]: from operator import *
In [261]: sorted(statuses.items(),key=lambda x:getitem(x[1],'position'))
Out[261]:
[('accepted', {'position': 1, 'status_for': 'dev'}),
('approved', {'position': 1, 'status_for': 'owner'}),
('pending', {'position': 1, 'status_for': 'all'}),
('rejected - owner', {'position': 2, 'status_for': 'owner'}),
('cancelled', {'position': 2, 'status_for': 'all'}),
('rejected - developer', {'position': 3, 'status_for': 'dev'}),
('closed', {'position': 5, 'status_for': 'dev'})]