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

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

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

3416
Gern Blanston 5 Мар 2009 в 03:49
9
Структура данных словаря не имеет собственного порядка. Вы можете выполнить итерацию, но нет ничего, что могло бы гарантировать, что итерация будет следовать какому-либо определенному порядку. Это сделано специально, поэтому лучше всего использовать другую структуру данных для представления.
 – 
Daishiman
5 Июл 2010 в 06:08
135
«sorted ()» может работать со словарями (и возвращает список отсортированных ключей), поэтому я думаю, что он знает об этом. Не зная его программы, абсурдно говорить кому-то, что они используют неправильную структуру данных. Если быстрый поиск - это то, что вам нужно в 90% случаев, то, вероятно, вам нужен диктат.
 – 
bobpaul
15 Фев 2013 в 23:04
Все три вывода (ключи, значения, оба) для сортировки словарей описаны здесь в ясном и кратком стиле: stackoverflow.com/questions/16772071/sort-dict-by-value-python
 – 
JStrahl
7 Мар 2016 в 13:14
2
Базовый класс можно не заказывать, но OrderedDict, конечно, можно .
 – 
Taylor D. Edmiston
9 Сен 2017 в 04:10
1
В Python 3.6+ словари сохраняют порядок вставки. Это, конечно, не то же самое, что возможность сортировать их по значению, но, с другой стороны, уже нельзя утверждать, что «структура данных словаря не имеет собственного порядка».
 – 
Konrad Kocik
31 Дек 2018 в 16:30

31 ответ

Лучший ответ

Python 3.7+ или CPython 3.6

Dicts сохраняет порядок вставки в Python 3.7+. То же самое в CPython 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}

Или

>>> dict(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, поскольку распаковка запрещена, мы можем использовать

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

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

import collections

sorted_dict = collections.OrderedDict(sorted_x)
6567
wjandrea 22 Ноя 2020 в 22:29
50
Для таймингов по различным схемам сортировки словарей по схемам значений: writeonly.wordpress.com/2008/08/30/…
 – 
Gregg Lind
14 Мар 2009 в 20:55
194
sorted_x.reverse() даст вам порядок по убыванию (по второму элементу кортежа)
 – 
saidimu apale
3 Май 2010 в 09:24
498
Саидиму: Поскольку мы уже используем sorted(), гораздо эффективнее передать аргумент reverse=True.
 – 
rmh
5 Июл 2010 в 06:59
129
В python3 я использовал лямбда: sorted(d.items(), key=lambda x: x[1]). Будет ли это работать в Python 2.x?
 – 
Benbob
15 Фев 2011 в 18:05
4
Где я могу узнать больше об использовании key=lambda item :item[1], пожалуйста? Часть, которую я не совсем понимаю, это item[1], это потому, что когда мы делаем x.items(), он возвращает пары ключ-значение, и с этим мы можем подключиться к значению, выполнив item[1] ?
 – 
UdonN00dle
7 Ноя 2021 в 02:56

Начиная с 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)

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

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 < a href = "http://bugs.python.org/issue27350" rel = "noreferrer"> "Компактный и упорядоченный dict" в Python 3.6 теперь мы сможем использовать встроенный dict для поддержки вставить заказ !!

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

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

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

Во-первых, потому что в некоторых случаях упрощает диспетчеризацию при реализации функций и методов.

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

Раймонд Хеттингер любезно предоставил документацию, объясняющую "whatsnew36) не придирки, но цитата была немного пессимистичной ;-). Он продолжается как «(это может измениться в будущем, но желательно иметь эту новую реализацию dict на языке в нескольких выпусках, прежде чем изменять спецификацию языка, чтобы требовать семантику сохранения порядка для всех текущих и будущих реализаций Python; это также помогает сохранить обратную совместимость со старыми версиями языка, в которых все еще действует случайный порядок итераций, например Python 3.5) ".

Так же, как и в некоторых человеческих языках (например, немецком), использование формирует язык, и воля теперь была объявлена ​​... в whatsnew36.

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

В письме в список разработчиков python Гвидо ван Россум заявил:

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

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

85
Dilettant 16 Дек 2017 в 18:47
Спасибо за предостережение, очень признателен - поскольку в мой ответ были вплетены смайлы и, возможно, смайлы, это должно указывать на то, что изменение огромное, но, конечно, доступно только для CPython (эталонная реализация) и PyPy. Для чего-то совершенно другого ... Я редко говорю о деталях, не связанных с реализацией, при написании человеко-машинных инструкций. Если бы это был только Jython ;-) ... У меня не хватило бы смелости написать это.
 – 
Dilettant
10 Сен 2016 в 23:22
OrderedDict определенно не выпадет; вместо этого он станет тонкой оберткой вокруг текущей реализации dict (так что вы можете добавить, что он также станет более компактным). Добавление этого фрагмента с ImportError не самая лучшая идея, поскольку вводит читателей в заблуждение, что OrderedDict бесполезен.
 – 
Dimitris Fasarakis Hilliard
10 Дек 2016 в 16:33
В ответ на этот ответ и структурированные словари я разместил новый ответ. Приветствуется обратная связь!
 – 
Bram Vanroy
2 Мар 2018 в 19:49

В последней версии 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 ведет себя как обычный диктатор:

>>> 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)])
180
Peter Mortensen 3 Апр 2014 в 20:59
6
Вопрос не в этом: речь идет не о поддержании порядка ключей, а о «сортировке по значению».
 – 
Nas Banov
5 Июл 2010 в 11:07
10
Банов: это НЕ сортировка по ключу. это сортировка по порядку, мы создаем элементы. в нашем случае мы сортируем по значению. к сожалению, 3-элементный dict был, к сожалению, выбран, поэтому порядок был таким же при сортировке voth по значению и ключу, поэтому я расширил образец dict.
 – 
mykhal
5 Июл 2010 в 14:56
sorted(d.items(), key=lambda x: x[1]) Вы можете объяснить, что означает x, почему он может преобразовать x[1] в лямбда? Почему это не может быть x[0]? Большое спасибо!
 – 
JZAU
8 Ноя 2013 в 09:12
1
d.items() возвращает похожий на список контейнер кортежей (key, value). [0] обращается к первому элементу кортежа - ключу - а [1] обращается ко второму элементу - значению.
 – 
BallpointBen
10 Апр 2018 в 17:29
2
Примечание. Начиная с версии 3.6 (как деталь реализации CPython / PyPy) и с версии 3.7 (как гарантия языка Python), простой dict также является упорядоченным, поэтому вы можете просто заменить OrderedDict на dict для кода, работающего на современном Python. OrderedDict на самом деле больше не нужен, если только вам не нужно изменить порядок существующего dictmove_to_end / popitem) или вам нужно, чтобы сравнения на равенство были чувствительными к порядку. Он использует намного больше памяти, чем простой dict, поэтому, если вы можете, dict - это то, что вам нужно.
 – 
ShadowRanger
4 Сен 2019 в 16:09

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

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

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

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])

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

1558
Boris Verkhovskiy 10 Мар 2020 в 17:42
39
Это тоже хорошо, но key=operator.itemgetter(1) должно быть более масштабируемым для повышения эффективности, чем key=d.get
 – 
smci
10 Дек 2011 в 01:18
12
sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True) и for key, val in sorted_keys: print "%s: %d" % (key, val) - itemgetter создает функцию при ее вызове, вы не используете ее напрямую, как в вашем примере. И простая итерация в dict использует ключи без значений
 – 
Izkata
20 Авг 2014 в 00:21
28
Я пришел из будущего, чтобы рассказать вам о collections.Counter, в котором есть метод most_common, который может вас заинтересовать :)
 – 
Eevee
25 Июн 2017 в 23:47

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

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

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

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

52
Peter Mortensen 28 Ноя 2017 в 16:44
Обратите внимание, что вы итерируете словарь и извлекаете значения по их ключу, поэтому с точки зрения производительности это не оптимальное решение.
 – 
Ron Klein
21 Сен 2016 в 11:00
1
@Dejell: как говорит автор, он интерпретирует вопрос как «могу ли я получить список ключей, отсортированных по значениям». Нам не нужны значения в результате, они есть в словаре.
 – 
Max
12 Янв 2019 в 06:19

Это код:

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}

Рофл

{'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}
31
icedwater 2 Мар 2016 в 10:42

Попробуйте следующий подход. Давайте определим словарь 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
31
Peter Mortensen 24 Май 2018 в 02:11
Потрясающие! for key, value in sorted(mydict.iteritems(), key=lambda (k,v): v["score"]): позволяет сортировать по подключам
 – 
Andomar
7 Июл 2017 в 22:08
Это не работает в более поздних версиях python, которые не поддерживают распаковку кортежей и где dicts больше не имеют iteritems ()
 – 
lb_so
5 Июн 2021 в 13:30

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

>>> 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)])
25
Peter Mortensen 3 Апр 2014 в 21:04
7
Чем это отличается от ответа Ивана Саса?
 – 
Peter Mortensen
3 Апр 2014 в 21:07

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

>>> 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(), тогда вы будете выполнять итерацию в отсортированном порядке по значению.

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

20
malthe 26 Сен 2014 в 02:56
Можем ли мы изменить порядок сортировки, прямо сейчас это отправка, но я хочу отмену.
 – 
Suleman Elahi
6 Фев 2020 в 15:15
Afaik вам придется отрицать свои значения, чтобы отменить порядок
 – 
malthe
6 Фев 2020 в 16:14

Начиная с 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.

31
Peter Mortensen 29 Сен 2022 в 16:59
Работает отлично! dict(sorted(words.items(), key=lambda x: x[1], reverse=True)) для DESC
 – 
vizyourdata
19 Ноя 2018 в 23:10

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

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

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

sorted((value,key) for (key,value) in mydict.items())
111
Justin Batch 12 Мар 2019 в 08:18
10
... и как и в случае с ответом Хэнка Гея, вам не нужны квадратные скобки. sorted () с радостью примет любую итерацию, например выражение генератора.
 – 
John Fouhy
5 Мар 2009 в 04:45
Возможно, вам все равно придется поменять местами элементы кортежа (значение, ключ), чтобы в итоге получился (ключ, значение). Тогда необходимо другое понимание списка. [(key, value) for (value, key) in sorted_list_of_tuples]
 – 
saidimu apale
3 Май 2010 в 09:22
2
Нет, квадратные скобки лучше оставить, потому что sorted все равно придется перестраивать список, и перестройка из gencomp будет быстрее. Хорошо для кодгольфинга, плохо для скорости. Оставьте уродливую версию ([]).
 – 
Jean-François Fabre
8 Дек 2017 в 00:21
Я запутался, это возвращает массив кортежей, а не словарь. IMO, вам не хватает части понимания dict: {x: v for x, v in sorted((value, key) for (key, value) in mydict.items())}
 – 
melMass
17 Июн 2022 в 15:15

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

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

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

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")
14
Bram Vanroy 19 Фев 2021 в 12:00
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
16
Argun 1 Ноя 2010 в 15:16
2
Вопрос был: сортировка по значению, а не по ключам ... Мне нравится видеть функцию. Вы можете импортировать коллекции и, конечно, использовать отсортированные (data.values ())
 – 
Remi
30 Авг 2011 в 04:38

Используйте 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)]
10
ponty 19 Окт 2011 в 10:25

Конечно, помните, что вам нужно использовать 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 или более поздней версии.

17
Georgy 17 Май 2019 в 19:17
1
обычные словари Python не сохраняют исходный порядок - в Python 3.7 он сохраняется.
 – 
gerrit
19 Дек 2018 в 20:13

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

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)
19
Peter Mortensen 29 Сен 2022 в 16:53
Это единственный ответ, который до сих пор работал в python 2.7.
 – 
rkochev
19 Янв 2021 в 15:44
Конец жизни Python 2 был в 2020 году.
 – 
Peter Mortensen
29 Сен 2022 в 16:54

Это работает в 3.1.x:

import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)
8
Nathaniel Ford 6 Ноя 2012 в 23:27

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

9
Petr Viktorin 24 Янв 2012 в 23:50

Я только что освоил соответствующий навык на 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))

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

# Ascending 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')]
11
Peter Mortensen 29 Сен 2022 в 16:58
Если вы хотите распечатать его в исходном формате, вы должны сделать: print ([(k, v) for v, k in sorted ([(v, k) for k, v in 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)]
 – 
Hermes Morales
4 Май 2020 в 23:14

Для полноты картины я публикую решение с использованием 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)]
8
Abhijit 23 Мар 2013 в 18:19

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

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

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

from collections import Counter

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


>> [('python', 5), ('world', 3), ('hello', 1)]
22
Eamonn Kenny 7 Окт 2021 в 13:56

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

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)]
1105
Suresh2692 10 Янв 2020 в 12:43
Из того, что я видел (документы .python.org / 2 / library /…), существует класс OrderedDict, который можно сортировать и сохранять порядок, оставаясь при этом словарем. Из примеров кода вы можете использовать лямбда для сортировки, но я лично не пробовал: P
 – 
UsAndRufus
20 Фев 2013 в 14:38
73
Я бы предпочел key=lambda (k, v): v лично
 – 
Claudiu
10 Апр 2015 в 02:08
Разве это не должно быть возвращение упорядоченного списка ключей (отсортированных по значениям), а не кортежей (k,v)? Вот что я получаю с Python 2.7.10. @Nyxynyx добавьте параметр reverse = True для сортировки в порядке убывания.
 – 
dhj
16 Ноя 2015 в 19:49
49
Мне тоже нравится этот синтаксис (k, v), но он недоступен в Python 3, где распаковка параметра кортежа была удалена.
 – 
Bob Stein
5 Фев 2016 в 20:53
1
Если вы заключите это в экземпляр OrderedDict(), вы получите (упорядоченный) dict вместо списка кортежей!
 – 
tsveti_iko
21 Мар 2019 в 13:30

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

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]
27
S.Lott 5 Мар 2009 в 04:52
months = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31,
          "June": 30, "July": 31, "August": 31, "September": 30, "October": 31,
          "November": 30, "December": 31}

def mykey(t):
    """ Customize your sorting logic using this function.  The parameter to
    this function is a tuple.  Comment/uncomment the return statements to test
    different logics.
    """
    return t[1]              # sort by number of days in the month
    #return t[1], t[0]       # sort by number of days, then by month name
    #return len(t[0])        # sort by length of month name
    #return t[0][-1]         # sort by last character of month name


# Since a dictionary can't be sorted by value, what you can do is to convert
# it into a list of tuples with tuple length 2.
# You can then do custom sorts by passing your own function to sorted().
months_as_list = sorted(months.items(), key=mykey, reverse=False)

for month in months_as_list:
    print month
4
lessthanl0l 14 Фев 2014 в 03:59

Словари нельзя отсортировать, но из них можно составить отсортированный список.

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

sorted(d.values())

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

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))
261
Roberto Bonvallet 16 Сен 2014 в 21:26
В каком порядке размещены ключи с одинаковым значением? Сначала я отсортировал список по ключам, а затем по значениям, но порядок ключей с одинаковым значением не сохраняется.
 – 
SabreWolfy
18 Июн 2012 в 14:04
7
Dicts теперь можно сортировать, начиная с CPython 3.6 и всех других реализаций Python, начиная с 3.7.
 – 
Boris Verkhovskiy
24 Апр 2020 в 22:38
Верно в то время, но теперь словари python сохраняют порядок, в котором элементы были вставлены уже по умолчанию. И поэтому их можно сортировать.
 – 
c8999c 3f964f64
11 Мар 2022 в 11:21

Использование Python 3.5

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

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)])
120
Peter Mortensen 29 Сен 2022 в 16:50
Можете ли вы объяснить, что делает itemgetter в этом примере? в противном случае это кажется таким же загадочным, как использование лямбы
 – 
c8999c 3f964f64
11 Мар 2022 в 11:29

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

$ 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
10
juhoh 30 Окт 2011 в 23:42

В 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.

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

41
sweetdream 22 Авг 2013 в 12:38

Вот решение с использованием 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')]
15
Scott 20 Июн 2015 в 04:44

Если значения числовые, вы также можете использовать Counter из < a href = "https://docs.python.org/library/collections.html" rel = "noreferrer"> коллекции .

from collections import Counter

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

>> [('python', 5), ('world', 3), ('hello', 1)]    
50
Georgy 17 Май 2019 в 16:48
Как насчет того, если ваш словарь >>> x = {'hello': 1, 'python': 5, 'world': 300}
 – 
James Sapam
28 Дек 2013 в 17:17
Counter({'hello':1, 'python':5, 'world':300}).most_common() дает [('world', 300), ('python', 5), ('hello', 1)]. Это действительно работает для любого сортируемого типа значения (хотя многие другие операции счетчика требуют, чтобы значения были сопоставимы с целыми числами).
 – 
lvc
28 Дек 2013 в 17:58

Часто бывает очень удобно использовать 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)

Теперь вы можете узнать имя и счет, скажем, второго лучшего игрока (индекс = 1), очень питонически следующим образом:

player = best[1]
player.name
    'Richard'
player.score
    7
83
vallentin 24 Апр 2017 в 05:11
Как я могу преобразовать его обратно в словарь?
 – 
rowana
7 Фев 2017 в 23:31
As_list = [Player (v, k) для (k, v) в d.items ()] as_dict = dict ((p.name, p.score) для p в as_list)
 – 
Remi
23 Фев 2017 в 15:31