Как отсортировать словарь по значению?


3422

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

Я могу сортировать по ключам, но как я могу сортировать по значениям?

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


9
Структура данных словаря не имеет собственного порядка. Вы можете выполнить итерацию, но нет ничего, что могло бы гарантировать, что итерация будет следовать какому-либо определенному порядку. Это сделано специально, поэтому лучше всего использовать другую структуру данных для представления.
Daishiman

135
«sorted ()» может работать со словарями (и возвращает список отсортированных ключей), поэтому я думаю, что он знает об этом. Не зная его программы, абсурдно говорить кому-то, что они используют неправильную структуру данных. Если быстрый поиск - это то, что вам нужно в 90% случаев, то, вероятно, вам нужен диктат.
Бобпол

Все три выхода (ключи, значения, оба) для словарей сортировки представлены здесь в ясном и лаконичном стиле: stackoverflow.com/questions/16772071/sort-dict-by-value-python
JStrahl

2
@Daishiman Базовый класс может быть не упорядочен, но, конечно, OrderedDict .
Тейлор

1
В Python 3.6+ словари сохраняют порядок вставки. Это, конечно, не то же самое, что возможность сортировать их по значению, но, с другой стороны, уже нельзя утверждать, что «структура данных словаря не имеет собственного порядка».
Конрад Коцик

Ответы:


4961

Python 3.6+

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
{k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

Старый Питон

Сортировать словарь невозможно, только чтобы получить представление отсортированного словаря. Словари по своей природе беспорядочные, а другие типы, такие как списки и кортежи, - нет. Таким образом, вам нужен упорядоченный тип данных для представления отсортированных значений, который будет списком - вероятно, списком кортежей.

Например,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_xбудет список кортежей, отсортированный по второму элементу в каждом кортеже. dict(sorted_x) == x,

А для желающих отсортировать по ключам вместо значений:

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

В Python3, поскольку распаковка запрещена [1], мы можем использовать

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[1])

Если вы хотите вывод как дикт, вы можете использовать collections.OrderedDict:

import collections

sorted_dict = collections.OrderedDict(sorted_x)

43
время для сортировки различных словарей по схемам значений: writeonly.wordpress.com/2008/08/30/…
Грегг Линд

164
sorted_x.reverse()даст вам нисходящий порядок (по второму элементу кортежа)
saidimu apale

414
saidimu: Поскольку мы уже используем sorted(), гораздо эффективнее передать reverse=Trueаргумент.
2010 года

121
В Python3 я использовал лямбда: sorted(d.items(), key=lambda x: x[1]). Будет ли это работать в Python 2.x?
Кейо

84
OrderedDict добавлен в коллекции в 2.7. Пример сортировки показан по адресу: docs.python.org/library/…
monkut,

1264

Так просто как: sorted(dict1, key=dict1.get)

Ну, на самом деле можно сделать «сортировку по значениям словаря». Недавно мне пришлось сделать это в Code Golf (вопрос о переполнении стека Code golf: Word частотная диаграмма ). Сокращенно, проблема была в следующем: по тексту подсчитать, как часто встречается каждое слово, и отобразить список главных слов, отсортированных по убыванию частоты.

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

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
    d[w] += 1

затем вы можете получить список слов, упорядоченных по частоте использования, sorted(d, key=d.get)- сортировка перебирает ключи словаря, используя количество вхождений слов в качестве ключа сортировки.

for w in sorted(d, key=d.get, reverse=True):
    print(w, d[w])

Я пишу это подробное объяснение, чтобы проиллюстрировать, что люди часто подразумевают под «я могу легко отсортировать словарь по ключу, но как я могу отсортировать по значению» - и я думаю, что в оригинальном сообщении была попытка решить эту проблему. И решение состоит в том, чтобы сделать вид списка ключей, основанный на значениях, как показано выше.


32
Это также хорошо, но key=operator.itemgetter(1)должно быть более масштабируемым для эффективности, чемkey=d.get
smci

3
@raylu Я наблюдаю поведение "не работает" с помощью itemgetter: ----- from operator import itemgetter d = {"a":7, "b":1, "c":5, "d":3} sorted_keys = sorted(d, key=itemgetter, reverse=True) for key in sorted_keys: print "%s: %d" % (key, d[key]) ----- -> b: 1 c: 5 a: 7 d: 3 Результаты меняются каждый раз, когда я запускаю код: странный , (извините, не могу получить код для правильного отображения)
bli

12
@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True)и for key, val in sorted_keys: print "%s: %d" % (key, val)- itemgetter создают функцию при ее вызове, вы не используете ее напрямую, как в вашем примере. И простая итерация для dict использует ключи без значений
Izkata

18
я пришел из будущего, чтобы рассказать вам о том collections.Counter, что есть most_commonметод, который может вас заинтересовать :)
Eevee

2
@ Eevee - есть вероятность того, что вас не поймут в коротких комментариях. Amuzing Tidbit: collections.Counterбыл добавлен в 2.7, который был выпущен почти ровно 7 лет назад! (Я не знал об этом тогда - плюс я бы избежал этого в код-гольфе с целью краткости, которая является единственной навязчивой идеей игры)
Нас Банов

859

Вы можете использовать:

sorted(d.items(), key=lambda x: x[1])

Это позволит отсортировать словарь по значениям каждой записи в словаре от наименьшего к наибольшему.

Чтобы отсортировать его в порядке убывания, просто добавьте reverse=True:

sorted(d.items(), key=lambda x: x[1], reverse=True)

Входные данные:

d = {'one':1,'three':3,'five':5,'two':2,'four':4}
a = sorted(d.items(), key=lambda x: x[1])    
print(a)

Вывод:

[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]

Из того, что я видел ( docs.python.org/2/library/… ), есть класс с именем OrderedDict, который можно сортировать и сохранять порядок, оставаясь в то же время словарем. Из примеров кода вы можете использовать лямбду для сортировки, но я лично не пробовал: P
UsAndRufus

53
Я бы предпочел key=lambda (k, v): vлично
Клавдиу

35
@Claudiu Мне также нравится этот (k, v)синтаксис, но он недоступен в Python 3, где была удалена распаковка параметров кортежа .
Боб Стейн

2
dict(sorted(d.items(), key=lambda x: x[1])),
Dr_Hope

3
Нет. Создание диктата из отсортированного списка кортежей снова убивает орден ...
Жан-Франсуа Фабр

233

Дики не могут быть отсортированы, но вы можете построить отсортированный список из них.

Сортированный список значений dict:

sorted(d.values())

Список пар (ключ, значение), отсортированных по значению:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))

В каком порядке размещены ключи с одинаковым значением? Сначала я отсортировал список по ключам, а затем по значениям, но порядок ключей с одинаковым значением не сохраняется.
SabreWolfy

1
Дики теперь можно сортировать, начиная с CPython 3.6 и всех других реализаций Python, начиная с 3.7
Борис

161

В недавнем Python 2.7 у нас появился новый тип OrderedDict , который запоминает порядок, в котором элементы были добавлены.

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

Чтобы создать новый упорядоченный словарь из оригинала, отсортировав по значениям:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

OrderedDict ведет себя как обычный dict:

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

5
Вопрос не в этом - речь идет не о поддержании порядка ключей, а о «сортировке по значению»
Нас Банов

10
@Nas Banov: это НЕ сортировка по ключу. это сортировка в порядке, мы создаем элементы. в нашем случае мы сортируем по значению. к сожалению, был выбран трехкомпонентный диктат, поэтому порядок был тот же, когда сортировали voth по значению и ключу, поэтому я расширил примерный диктат.
Михал

sorted(d.items(), key=lambda x: x[1])Можете ли вы объяснить, что xзначит, почему это может привести x[1]к лямбда? Почему этого не может быть x[0]? Большое спасибо!
JZAU

1
@Boern d.items()возвращает контейнер списков, похожий на список (key, value). [0]получает доступ к первому элементу кортежа - ключу - и [1]обращается ко второму элементу - значению.
BallpointBen

2
Примечание: В 3,6 (как деталь реализации CPython / PyPy) и в 3,7 ( в качестве гарантии на языке Python), простой dictявляется вставка заказывается, так что вы можете просто заменить OrderedDictс dictдля кода , работающего на современном языке Python. OrderedDictбольше не требуется, если только вам не нужно изменить порядок существующего dictmove_to_end/ popitem) или не нужно сравнение на равенство, чтобы учитывать порядок. Он использует гораздо больше памяти, чем обычный dict, поэтому, если вы можете, dictэто путь.
ShadowRanger

104

ОБНОВЛЕНИЕ: 5 ДЕКАБРЯ 2015 с использованием Python 3.5

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

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

Официальная документация OrderedDict также предлагает очень похожий пример, но с использованием лямбды для функции сортировки:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

86

Почти так же, как ответ Хэнка Гея :

sorted([(value,key) for (key,value) in mydict.items()])

Или слегка оптимизирован, как это было предложено Джоном Фухи:

sorted((value,key) for (key,value) in mydict.items())

9
... и как и в случае с ответом Хэнка Гея, вам не нужны квадратные скобки. sorted () с радостью примет любую итерацию, например выражение генератора.
Джон Фухи

Возможно, вам все еще придется поменять элементы кортежа (значение, ключ), чтобы получить (ключ, значение). Затем необходимо другое понимание списка. [(key, value) for (value, key) in sorted_list_of_tuples]
Саидиму Апале

нет, лучше оставить квадратные скобки, потому sortedчто в любом случае придется пересоздать список, и перестроение из gencomp будет быстрее. Хорошо для игры в гольф, плохо для скорости. Держи уродливую ([])версию.
Жан-Франсуа Фабр

75

Часто может быть очень удобно использовать namedtuple . Например, у вас есть словарь «имя» в качестве ключей и «оценка» в качестве значений, и вы хотите отсортировать по «оценка»:

import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}

сортировка с наименьшим количеством баллов:

worst = sorted(Player(v,k) for (k,v) in d.items())

сортировка с наибольшим количеством баллов:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

Теперь вы можете получить имя и счет, скажем, второго лучшего игрока (index = 1), очень Pythonly, как это:

player = best[1]
player.name
    'Richard'
player.score
    7

Как я могу преобразовать его обратно в словарь?
rowana

as_list = [Player (v, k) для (k, v) в d.items ()] as_dict = dict ((p.name, p.score) для p в as_list)
Remi

72

Начиная с Python 3.6 встроенный dict будет заказан

Хорошая новость: исходный сценарий использования OP для отображения пар, извлеченных из базы данных с уникальными строковыми идентификаторами в качестве ключей и числовыми значениями в качестве значений во встроенном Python v3.6 + dict, теперь должен соответствовать порядку вставки.

Если, скажем, результирующие выражения таблицы в два столбца из запроса к базе данных, как:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

будет храниться в двух кортежах Python, k_seq и v_seq (выровненных по числовому индексу и, конечно же, с одинаковой длиной), затем:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

Разрешить вывод позже как:

for k, v in ordered_map.items():
    print(k, v)

уступая в этом случае (для нового Python 3.6+ встроенный dict!):

foo 0
bar 1
baz 42

в том же порядке на значение v.

Где в Python 3.5 установить на моей машине это в настоящее время дает:

bar 1
foo 0
baz 42

Подробности:

Как было предложено в 2012 году Рэймондом Хеттингером (см. Почту на python-dev с темой «Более компактные словари с более быстрой итерацией» ), а теперь (в 2016 году) объявлено в письме Виктора Стиннера к python-dev с темой «Python 3.6 dict становится компактный и получает приватную версию, а ключевые слова упорядочиваются « из-за исправления / реализации проблемы 27350 « компактный и упорядоченный дикт » в Python 3.6, теперь мы сможем использовать встроенный dict для поддержания порядка вставки !!

Надеемся, что это приведет к тонкому слою реализации OrderedDict в качестве первого шага. Как указывало @ JimFasarakis-Hilliard, некоторые видят варианты использования для типа OrderedDict и в будущем. Я думаю, что сообщество Python в целом тщательно проверит, выдержит ли это испытание временем, и какими будут следующие шаги.

Время переосмыслить наши привычки кодирования, чтобы не упустить возможности, открываемые стабильным упорядочением:

  • Ключевое слово аргументы и
  • промежуточное хранение

Первый, потому что в некоторых случаях он облегчает выполнение функций и методов.

Второе, поскольку это способствует более легкому использованию dicts в качестве промежуточного хранилища в технологических трубопроводах.

Рэймонд Хеттингер любезно предоставил документацию, объясняющую « Технология позади словарей Python 3.6 » - из своей презентации в Сан-Франциско Python Meetup Group 2016-DEC-08.

И, может быть, довольно много страниц с вопросами и ответами в Stack Overflow получат варианты этой информации, и многие высококачественные ответы также потребуют обновления для каждой версии.

Предостережение Emptor (но также см. Ниже обновление 2017-12-15):

Как справедливо замечает @ajcr: «Сохраняющий порядок аспект этой новой реализации считается деталью реализации и на нее не следует полагаться». (из whatsnew36 ) не гнида, а цитата была вырезана немного пессимистично ;-). Это продолжается как "(это может измениться в будущем, но желательно иметь эту новую реализацию dict в языке в течение нескольких выпусков, прежде чем изменять спецификацию языка, чтобы предписывать семантику сохранения порядка для всех текущих и будущих реализаций Python; это также помогает сохранить обратную совместимость со старыми версиями языка, где все еще действует случайный порядок итераций, например, Python 3.5). "

Как и в некоторых человеческих языках (например, в немецком), использование определяет язык, и завещание было объявлено ... в whatsnew36 .

Обновление 2017-12-15:

В письме к списку python-dev Гвидо ван Россум заявил:

Сделай это так. «Dict сохраняет порядок вставки» - это решение. Спасибо!

Таким образом, побочный эффект CPython версии 3.6 от порядка вставки dict теперь становится частью языковой спецификации (а не только детали реализации). Эта ветка почты также выявила некоторые отличительные цели дизайна, о collections.OrderedDictчем напомнил Рэймонд Хеттингер в ходе обсуждения.


15
Следует подчеркнуть предупреждение на странице «whatsnew», на которую вы ссылаетесь: сохраняющий порядок аспект этой новой реализации считается деталью реализации и на него не следует полагаться . Никто не должен предполагать, что dictтип будет соответствовать порядку вставки в их коде. Это не является частью определения языка, и реализация может измениться в любом будущем выпуске. Продолжайте использовать, OrderedDictчтобы гарантировать заказ.
Алекс Райли

@ajcr спасибо за предостережение, очень признателен - так как смайлики и, возможно, были включены в мой ответ, это должно указывать на то, что изменения огромны, но, конечно, доступны только для CPython (эталонная реализация) и PyPy. Для чего-то совершенно другого ... Я редко говорю о деталях, не связанных с реализацией, при кодировании команд человек-машина. Если бы это был только Jython ;-) ... У меня не было бы смелости написать это.
Дилетант

OrderedDictопределенно не будет отброшен; вместо этого он станет тонкой оболочкой для текущей реализации dict (так что вы можете добавить, что он тоже станет более компактным). Добавление этого фрагмента с ImportErrorне совсем лучшей идеей, потому что вводит в заблуждение читателей, которые OrderedDictбесполезны.
Димитрис Фасаракис Хиллиард

@ JimFasarakis-Hilliard спасибо за отзыв. «Совершенно лучшие идеи» заставили меня улыбнуться - будущее часто трудно предсказать. Но мне нравится, что ваше предложение проверит источники, попробуйте и обновите ответ соответственно. Еще раз спасибо.
Дилетант

8
@AlexRiley Это предупреждение больше не является точным. Python3.7 гарантирует упорядоченные словари.
gerrit

42

У меня была такая же проблема, и я решил ее так:

WantedOutput = sorted(MyDict, key=lambda x : MyDict[x]) 

(Люди, которые отвечают «Невозможно отсортировать диктовку», не читали вопрос! На самом деле, «Я могу сортировать по ключам, но как я могу сортировать по значениям?» Ясно означает, что ему нужен список ключи отсортированы по значению их значений.)

Обратите внимание, что порядок не определен (ключи с одинаковыми значениями будут в произвольном порядке в списке вывода).


1
Вы пропустите значение из результата
Dejell

Обратите внимание, что вы итерируете словарь и извлекаете значения по их ключу, поэтому с точки зрения производительности это не оптимальное решение.
Рон Кляйн

1
@Dejell: как говорит автор, он интерпретирует вопрос как «могу ли я получить список ключей, отсортированных по значениям». Нам не нужны значения в результате, они есть в словаре.
Макс

36

Если значения являются числовыми, вы также можете использовать их Counterиз коллекций .

from collections import Counter

x = {'hello': 1, 'python': 5, 'world': 3}
c = Counter(x)
print(c.most_common())

>> [('python', 5), ('world', 3), ('hello', 1)]    

а что если ваш словарь >>> x = {'hello': 1, 'python': 5, 'world': 300}
Джеймс Сапам

@yopy Counter({'hello':1, 'python':5, 'world':300}).most_common()дает [('world', 300), ('python', 5), ('hello', 1)]. Это на самом деле работает для любого типа сортируемых значений (хотя многие другие операции Counter требуют, чтобы значения были сопоставимы с целыми числами).
lvc 28.12.13

34

В Python 2.7 просто выполните:

from collections import OrderedDict
# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by key
OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

скопировать из: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

Наслаждаться ;-)


25

Это код:

import operator
origin_list = [
    {"name": "foo", "rank": 0, "rofl": 20000},
    {"name": "Silly", "rank": 15, "rofl": 1000},
    {"name": "Baa", "rank": 300, "rofl": 20},
    {"name": "Zoo", "rank": 10, "rofl": 200},
    {"name": "Penguin", "rank": -1, "rofl": 10000}
]
print ">> Original >>"
for foo in origin_list:
    print foo

print "\n>> Rofl sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
    print foo

print "\n>> Rank sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rank")):
    print foo

Вот результаты:

оригинал

{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}

Rofl

{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}

Ранг

{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}

25

Попробуйте следующий подход. Давайте определим словарь mydict со следующими данными:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

Если кто-то хочет отсортировать словарь по ключам, можно сделать что-то вроде:

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

Это должно вернуть следующий вывод:

alan: 2
bob: 1
carl: 40
danny: 3

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

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

Результат этой команды (сортировка словаря по значению) должен вернуть следующее:

bob: 1
alan: 2
danny: 3
carl: 40

Потрясающие! for key, value in sorted(mydict.iteritems(), key=lambda (k,v): v["score"]):позволяет сортировать по подразделу
Andomar

это дает мне синтаксическую ошибку около лямбды в Python3
Сулеман Элахи

21

Начиная с Python 3.6, dictобъекты теперь упорядочены по порядку вставки. Это официально в спецификациях Python 3.7.

>>> words = {"python": 2, "blah": 4, "alice": 3}
>>> dict(sorted(words.items(), key=lambda x: x[1]))
{'python': 2, 'alice': 3, 'blah': 4}

До этого вам приходилось пользоваться OrderedDict.

Документация Python 3.7 гласит:

Изменено в версии 3.7: Порядок словаря гарантированно является порядком вставки. Такое поведение было деталью реализации CPython от 3.6.


работает отлично! dict(sorted(words.items(), key=lambda x: x[1], reverse=True))для DESC
vizyourdata

20

Вы можете создать «инвертированный индекс», также

from collections import defaultdict
inverse= defaultdict( list )
for k, v in originalDict.items():
    inverse[v].append( k )

Теперь ваш обратный имеет значения; у каждого значения есть список применимых ключей.

for k in sorted(inverse):
    print k, inverse[k]

19

Вы можете использовать коллекции . Счетчик . Обратите внимание, что это будет работать как для числовых, так и для нечисловых значений.

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

7
Чем это отличается от ответа Ивана Саса ?
Питер Мортенсен

15

Вы можете использовать пропускающий словарь, который является словарем, который постоянно сортируется по значению.

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

Если вы используете keys(), values()илиitems() тогда вы будете перебирать в отсортированном порядке по значению.

Это реализовано с использованием структуры данных списка пропусков .


Можем ли мы изменить порядок сортировки, прямо сейчас, это отправка, но я хочу отклонение.
Сулеман Элахи

afaik, вам нужно будет отрицать ваши значения, чтобы изменить порядок
мальте

вау, я так не думаю ... спасибо.
Сулеман Элахи

14

Вы также можете использовать пользовательскую функцию, которую можно передать клавише.

def dict_val(x):
    return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)

12
from django.utils.datastructures import SortedDict

def sortedDictByKey(self,data):
    """Sorted dictionary order by key"""
    sortedDict = SortedDict()
    if data:
        if isinstance(data, dict):
            sortedKey = sorted(data.keys())
            for k in sortedKey:
                sortedDict[k] = data[k]
    return sortedDict

2
вопрос был: сортировка по значению, а не по ключам ... Мне нравится видеть функцию. Вы можете импортировать коллекции и, конечно, использовать отсортированные (data.values ​​())
Remi

10

Как указывает Dilettant , Python 3.6 теперь будет поддерживать порядок ! Я думал, что у меня будет функция, которую я написал, которая облегчает сортировку итерируемого (кортеж, список, dict). В последнем случае вы можете сортировать либо по ключам, либо по значениям, и это может учитывать числовое сравнение.Только для> = 3.6!

Когда вы пытаетесь использовать сортировку для итерируемого, который содержит, например, строки и целые числа, sorted () завершится ошибкой. Конечно, вы можете форсировать сравнение строк с помощью str (). Тем не менее, в некоторых случаях вы хотите сделать фактическое числовое сравнение, где 12меньше, чем 20(что не так при сравнении строк). Итак, я придумал следующее. Когда вы хотите явное числовое сравнение, вы можете использовать флаг, num_as_numкоторый попытается выполнить явную числовую сортировку, пытаясь преобразовать все значения в числа с плавающей точкой. Если это удастся, он выполнит числовую сортировку, иначе он прибегнет к сравнению строк.

Комментарии по улучшению или push-запросы приветствуются.

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")

9

Вот решение с использованием zip d.values()иd.keys() . Несколько строк по этой ссылке (в объектах словаря):

Это позволяет создавать пары (значение, ключ) с помощью zip (): pair = zip (d.values ​​(), d.keys ()).

Таким образом, мы можем сделать следующее:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]

9

Конечно, помните, вам нужно использовать, OrderedDictпотому что обычные словари Python не сохраняют первоначальный порядок.

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))

Если у вас нет Python 2.7 или выше, лучшее, что вы можете сделать, - это перебирать значения в функции генератора. (Существует OrderedDictдля 2.4 и 2.6 здесь , но

а) я не знаю, насколько хорошо это работает

а также

б) Вы должны скачать и установить его, конечно. Если у вас нет доступа с правами администратора, то, боюсь, опция отключена.)


def gen(originalDict):
    for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

Вы также можете распечатать каждое значение

for bleh, meh in gen(myDict):
    print(bleh, meh)

Пожалуйста, не забудьте удалить скобки после печати, если вы не используете Python 3.0 или выше


обычные словари Python не сохраняют первоначальный порядок - с Python 3.7 они сохраняют .
Gerrit

7

Используйте ValueSortedDict из dicts :

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]


6

Только что выучил соответствующий навык из Python для всех .

Вы можете использовать временный список для сортировки словаря:

#Assume dictionary to be:
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}

# create a temporary list
tmp = []

# iterate through the dictionary and append each tuple into the temporary list 
for key, value in d.items():
    tmptuple = (value, key)
    tmp.append(tmptuple)

# sort the list in ascending order
tmp = sorted(tmp)

print (tmp)

Если вы хотите отсортировать список в порядке убывания, просто измените исходную строку сортировки на:

tmp = sorted(tmp, reverse=True)

Используя понимание списка, один вкладыш будет:

#Assuming the dictionary looks like
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
#One liner for sorting in ascending order
print (sorted([(v, k) for k, v in d.items()]))
#One liner for sorting in descending order
print (sorted([(v, k) for k, v in d.items()], reverse=True))

Пример вывода:

#Asending order
[(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')]
#Descending order
[(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]

это сортировка по ключам, а не по значениям.
Рубель

Если вы хотите распечатать его в исходном формате, вы должны сделать: print ([(k, v) для v, k в отсортированном виде ([(v, k) для k, v в d.items ()])]). Вывод: [(«оранжевый», 1,0), («яблоко», 500,1), («ананас», 789,0), («банан», 1500,2)]. С [(k, v) для v, k в отсортированном ([(v, k) для k, v в d.items ()], reverse = True)] вывод: [('banana', 1500.2), («Ананас», 789,0), («Яблоко», 500,1), («Апельсин», 1,0)]
Гермес Моралес

5

Итерируйте через dict и сортируйте его по значениям в порядке убывания:

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1

5

Если ваши значения являются целыми числами, и вы используете Python 2.7 или новее, вы можете использовать collections.Counterвместо dict. most_commonМетод даст вам все элементы, упорядоченные по значению.


5

Ради полноты я выкладываю решение с использованием heapq . Обратите внимание, что этот метод будет работать как для числовых, так и для нечисловых значений.

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> x_items = x.items()
>>> heapq.heapify(x_items)
>>> #To sort in reverse order
>>> heapq.nlargest(len(x_items),x_items, operator.itemgetter(1))
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> heapq.nsmallest(len(x_items),x_items, operator.itemgetter(1))
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

4

Из-за требований сохранить обратную совместимость со старыми версиями Python, я думаю, что решение OrderedDict очень неразумно. Вы хотите что-то, что работает с Python 2.7 и более ранними версиями.

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

Я не согласен с выбором номер один, представленным в другом ответе, потому что он выбрасывает ключи.

Я использовал решение, упомянутое выше (код, показанный ниже), и сохранил доступ к ключам и значениям, и в моем случае упорядочение было по значениям, но важным было упорядочение ключей после упорядочения значений.

from collections import Counter

x = {'hello':1, 'python':5, 'world':3}
c=Counter(x)
print c.most_common()


>> [('python', 5), ('world', 3), ('hello', 1)]
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.