Сортировка вложенного словаря по значению и остаток по другому значению в 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']))