Python 2.5 словарь 2 сортировка ключей

У меня есть словарь из 200 000 элементов (ключи - строки, а значения - целые числа).

Каков наилучший / самый питонический способ распечатать элементы, отсортированные по убыванию значения, а затем по восходящему ключу (то есть сортировка с двумя ключами)?

 a = { 'keyC':1, 'keyB':2, 'keyA':1 }
b = a.items()
b.sort( key=lambda a:a[0])
b.sort( key=lambda a:a[1], reverse=True )
print b
>>>[('keyB', 2), ('keyA', 1), ('keyC', 1)]

См. Мой ответ на связанный вопрос здесь.

hughdbrown 17.07.2009 22:19
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
15
1
32 311
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Словари нельзя сортировать. Вам нужно отсортировать список предметов.

Предыдущие версии были неправильными. Если у вас числовое значение, его легко отсортировать в обратном порядке. Они сделают это. Но это не общее. Это работает только потому, что значение является числовым.

a = { 'key':1, 'another':2, 'key2':1 }

b= a.items()
b.sort( key=lambda a:(-a[1],a[0]) )
print b

Вот альтернатива, используя явную функцию вместо лямбда и cmp вместо ключевого параметра.

def valueKeyCmp( a, b ):
    return cmp( (-a[1], a[0]), (-b[1], b[0] ) )

b.sort( cmp= valueKeyCmp )
print b

Более общее решение - это на самом деле два разных вида

b.sort( key=lambda a:a[1], reverse=True )
b.sort( key=lambda a:a[0] )
print b

Спасибо, но это не касается порядка сортировки или двух ключевых свойств сортировки.

Kev 01.10.2008 17:02

Третий пример не выполняет сортировку по двум ключам, вторая сортировка отменяет первую.

Ricardo Reyes 01.10.2008 18:05

@ Рикардо Рейес: сортировка на питоне - стабильная сортировка. При сортировке сначала по меньшим ключам достигается конечный результат.

tzot 01.10.2008 18:06

@ S.Lott Спасибо. Одна точка .. b.sort (key = lambda a: (- a [1], a [0])) дает мне «TypeError: неверный тип операнда для унарного -: 'str'», тогда как b.sort (key = lambda a: (a [1] * - 1, a [0])) работает нормально. Не понимаю почему.

Kev 01.10.2008 18:58

@monty: ваши значения не числа, это строки. Проверьте repr () вашего словаря, чтобы узнать, есть ли у вас {'key': '1'} или нет. Возможно, вам понравится лямбда a: (- int (a [1]), a [0]), которая вызывает преобразование в int.

S.Lott 01.10.2008 19:03

Самый питонический способ сделать это - узнать немного больше о фактических данных - в частности, о максимальном значении, которое вы можете иметь, - а затем сделать это следующим образом:

def sortkey((k, v)): 
    return (maxval - v, k)

items = thedict.items()
items.sort(key=sortkey)

но если вы еще не знаете максимальное значение, поиск максимального значения означает повторный цикл через dict дополнительное время (с max(thedict.itervalues())), что может быть дорогостоящим. В качестве альтернативы, версия решения S.Lott с ключевыми функциями:

def sortkey((k, v)): 
    return (-v, k)

items = thedict.items()
items.sort(key=sortkey)

Альтернативой, которая не заботится о типах, будет функция сравнения:

def sortcmp((ak, av), (bk, bv)):
    # compare values 'in reverse'  
    r = cmp(bv, av)
    if not r:
        # and then keys normally
        r = cmp(ak, bk)
    return r

items = thedict.items()
items.sort(cmp=sortcmp) 

и это решение действительно работает для любого типа ключа и значения, с которыми вы хотите смешивать сортировку по возрастанию и убыванию в одном и том же ключе. Если вы цените краткость, вы можете написать sortcmp как:

def sortcmp((ak, av), (bk, bv)):
    return cmp((bk, av), (ak, bv))

Знать максимальное значение бесполезно; используйте любое значение в качестве максимального значения. 0 сразу приходит в голову, как предположил С.Лотт. ;)

tzot 01.10.2008 18:09

Вы можете использовать что-то вроде этого:

dic = {'aaa':1, 'aab':3, 'aaf':3, 'aac':2, 'aad':2, 'aae':4}

def sort_compare(a, b):
    c = cmp(dic[b], dic[a])
    if c != 0:
        return c
    return cmp(a, b)

for k in sorted(dic.keys(), cmp=sort_compare):
    print k, dic[k]

Однако не знаю, насколько он питонический :)

data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), key=lambda x: (-1*x[1], x[0])):
    print key, value

На мой взгляд, это наиболее питоническое решение, которое проще всего понять.

Jesse Shieh 24.06.2009 19:12

Сортировка по значению, а не по ключу.

Nikola Kotur 19.05.2011 13:33

Основываясь на решениях Томаса Воутерса и Рикардо Рейеса:

def combine(*cmps):
    """Sequence comparisons."""
    def comparator(a, b):
        for cmp in cmps:
            result = cmp(a, b):
            if result:
                return result
        return 0
    return comparator

def reverse(cmp):
    """Invert a comparison."""
    def comparator(a, b):
        return cmp(b, a)
    return comparator

def compare_nth(cmp, n):
    """Compare the n'th item from two sequences."""
    def comparator(a, b):
        return cmp(a[n], b[n])
    return comparator

rev_val_key_cmp = combine(
        # compare values, decreasing
        reverse(compare_nth(1, cmp)),

        # compare keys, increasing
        compare_nth(0, cmp)
    )

data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), cmp=rev_val_key_cmp):
    print key, value

>>> keys = sorted(a, key=lambda k: (-a[k], k))

или же

>>> keys = sorted(a)
>>> keys.sort(key=a.get, reverse=True)

потом

print [(key, a[key]) for key in keys]
[('keyB', 2), ('keyA', 1), ('keyC', 1)]

Другие вопросы по теме