Сортировка вложенного словаря по значению и остаток по другому значению в Python
Рассмотрим этот формат словаря.
{'KEY1':{'name':'google','date':20100701,'downloads':0},
'KEY2':{'name':'chrome','date':20071010,'downloads':0},
'KEY3':{'name':'python','date':20100710,'downloads':100}}
Сначала мне нужен словарь, отсортированный по загрузкам, а затем все элементы без загрузки, отсортированные по дате. Очевидно, словарь не может быть отсортирован, мне просто нужен отсортированный список ключей, которые я могу перебрать.
['KEY3','KEY1','KEY2']
Я уже сортирую список по значению с помощью sorted
, но как мне сортировать по второму значению?
Ответы
Ответ 1
Используйте аргумент key
для sorted()
. Он позволяет указать функцию, которая, учитывая сортировку фактического элемента, возвращает значение, которое должно быть отсортировано. Если это значение является кортежем, то оно сортируется как сортировка сортиментов - по первому значению, а затем по второму значению.
sorted(your_list, key=lambda x: (your_dict[x]['downloads'], your_dict[x]['date']))
Ответ 2
Вы можете передать key
функцию sorted
, которая возвращает кортеж, содержащий две вещи, которые вы хотите сортировать. Предполагая, что ваш большой словарь называется d
:
def keyfunc(tup):
key, d = tup
return d["downloads"], d["date"]
items = sorted(d.items(), key = keyfunc)
Вы можете сделать это с помощью lambda
, если хотите, но это, вероятно, более понятно. Здесь эквивалентный код на основе лямбда:
items = sorted(d.items(), key = lambda tup: (tup[1]["downloads"], tup[1]["date"]))
Кстати, так как вы упомянули, что сначала хотите отсортировать "закачки", эти два примера сортируются в соответствии с подсчетом загрузки в порядке возрастания. Однако из контекста это звучит так, как будто вы можете сортировать в порядке убывания загрузки, и в этом случае вы скажете
return -d["downloads"], d["date"]
в keyfunc
. Если вы хотите что-то вроде сортировки в порядке возрастания для ненулевых номеров загрузки, то после этого все записи с нулевой загрузкой вы можете сказать что-то вроде
return (-d["downloads"] or sys.maxint), d["date"]
Ответ 3
Мой другой ответ был неправильным (как и большинство ответов здесь)
sorted_keys = sorted((key for key in outer_dict if outer_dict[key]['downloads']),
key=lambda x: (outer_dict[key]['downloads'],
outer_dict[key]['downloads'])
reverse=True)
sorted_keys += sorted((key for key in outer_dict if not outer_dict[key]['downloads']),
key=lambda x: outer_dict[key]['date'])
Это создаст список с отсортированными в порядке убывания в начале списка, а остальные элементы, которые не были загружены, отсортированы по дате после тех, которые у вас есть.
Но на самом деле последняя часть Ответ Eli Courtwrights является лучшей.
Ответ 4
a = {'KEY1':{'name':'google','date':20100701,'downloads':0},
'KEY2':{'name':'chrome','date':20071010,'downloads':0},
'KEY3':{'name':'python','date':20100710,'downloads':100}}
z = a.items()
z.sort(key=lambda x: (x[1]['downloads'], x[1]['date']))