Сортировка словаря по значению не из этого словаря
Мне нужно отсортировать словарь, в определенном порядке, который в самом словаре не определен.
Я получаю с БД такой вот словарь, и мне нужно его вывести так, чтобы сначала шла еда, а потом остальное.
tav = {'Газ': 23.0, 'Отопление': 900.0, 'Школа/Кружки': 450.0, 'ОСББ/УК': 481.0, 'Молочка': 35.0, 'Сладости': 40.0, 'Фрукты и Овощи': 50.0}
И вот порядок сортировки. Сначала должны выводиться данные по фруктам, потом по молочке и т.д.
cats = ['Фрукты и Овощи', 'Молочка', 'Сладости', 'Газ', 'Отопление']
#Перебираю каждый элемент словаря, и если ключ есть в CATS, то я ему добавляю нужный порядковый номер.
new_list = []
for i in tav:
if i in cats:
a = cats.index(i)
else: a = 99
new_list.append((i, tav[i], a)) # И добавляю все это в виде кортежа
#Получается так:
#[('Газ', 23.0, 3), ('Отопление', 900.0, 4), ('Школа/Кружки', 450.0, 99), ('ОСББ/УК', 481.0, 99), ('Молочка', 35.0, 1), ('Сладости', 40.0, 2), ('Фрукты и Овощи', 50.0, 0)]
# Сортирую по нужному значению
new_list = sorted(new_list, key=lambda b: b[2])
#И снова закидываю все в словарь.
final_dict = {}
for tuple in new_list:
final_dict[tuple[0]] = tuple[1]
И наконец, получаю то что мне надо.
#{'Фрукты и Овощи': 50.0, 'Молочка': 35.0, 'Сладости': 40.0, 'Газ': 23.0, 'Отопление': 900.0, 'ОСББ/УК': 481.0, 'Школа/Кружки': 450.0}
Скажите, это совсем говнокод?
Как это сделать проще?
Ответы (3 шт):
Проще пройтись по категориям, а потом добавить то, что вне категорий
final_dict = {}
for cat in cats:
if cat in tav:
final_dict[cat] = tav[cat]
for k, v in tav.items():
if k not in final_dict:
final_dict[k] = v
// Не уверен, что словарь в python - это ordered map, вероятно порядок ключей ничем не гарантирован, тут нужно мнение знатоков
можно так:
import sys
def myindex(el):
try:
return cats.index(el)
except ValueError:
return sys.maxsize
new_dict = dict(sorted(tav.items(), key=lambda x: (myindex(x[0]), x[0]))))
>>> new_dict
{'Фрукты и Овощи': 50.0, 'Молочка': 35.0, 'Сладости': 40.0, 'Газ': 23.0, 'Отопление': 900.0, 'ОСББ/УК': 481.0, 'Школа/Кружки': 450.0}
если у вас в списке указан изначально верный порядок, то отсортирует именно по нему. как видим при сортировке мы указываем два параметра, первый это как раз сортировка, как у вас в списке, второй уже по оставшимся ключам по алфавиту.
далее, для чего нам функция с обработкой исключений. Если ее не будет и будем просто делать сортировку по key=lambda x: (cats.index(x[0]), то вылетит ошибка, что отсутствуют значения, поэтому в функции мы присваиваем отсутствующим значениям максимальное число (в вашем случае можно и 99, если вас это устраивает и словарь небольшой)
вариант похожий на уже предложенный:
final_dict = dict(sorted(tav.items(),
key=lambda x: cats.index(x[0])
if x[0] in cats
else float('inf')))
'''
{'Фрукты и Овощи': 50.0,
'Молочка': 35.0,
'Сладости': 40.0,
'Газ': 23.0,
'Отопление': 900.0,
'Школа/Кружки': 450.0,
'ОСББ/УК': 481.0}