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

avatar
Gern Blanston
5 марта 2009 в 00:49
3732118
34
3417

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

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

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

Источник
Daishiman
5 июля 2010 в 02:08
9

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

bobpaul
15 февраля 2013 в 19:04
135

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

JStrahl
7 марта 2016 в 10:14
0

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

Taylor Edmiston
9 сентября 2017 в 01:10
2

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

Konrad Kocik
31 декабря 2018 в 13:30
1

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

Ответы (34)

avatar
Devin Jeanpierre
5 марта 2009 в 00:59
5856

Python 3.7+ или CPython 3.6

Сохраняет порядок вставки в 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}

Старый Python

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

Например,

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)
Gregg Lind
14 марта 2009 в 17:55
46

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

saidimu apale
3 мая 2010 в 05:24
181

sorted_x.reverse() даст вам порядок по убыванию (по второму элементу кортежа)

rmh
5 июля 2010 в 02:59
456

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

Keyo
15 февраля 2011 в 15:05
125

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

monkut
24 апреля 2011 в 06:31
86

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

haneulkim
25 апреля 2021 в 12:38
0

если значение имеет одинаковое значение, как обеспечить, чтобы значение с меньшим ключом было первым?

Uros Pocek
26 июня 2021 в 13:17
0

map = {k: v for k, v in sorted (map.items (), key = lambda item: item [1], reverse = True)} используйте это для обратного (по убыванию) порядка.

Rabi
6 августа 2021 в 13:40
1

Почему сейчас это не работает {k: v для k, v в sorted (x.items (), key = lambda item: item [1])}

avatar
Wira Bhakti
26 февраля 2019 в 04:12
1

Помимо использования встроенного модуля и т. Д., Я пытаюсь решить эту проблему вручную ... first Я создал функцию, задача которой - возвращать минимальное значение каждого элемента dict:

def returnminDict(_dct):
    dict_items = _dct.items()
    list_items = list(dict_items)
    init_items = list_items[0]
    for i in range(len(list_items)):
        if list_items[i][1] > init_items[1]:
           continue
        else:
           init_items = list_items[i]
    return init_items

Второй , теперь у нас есть функция, которая возвращает элемент с минимальным значением, затем я делаю новый dict, а затем перебираю dict:

def SelectDictSort(_dct):
    new_dict = {}
    while _dct:
        mindict = returnminDict(_dct)
        new_dict.update(dict((mindict,)))
        _dct.pop(mindict[0])
    return new_dict

я пробую это SelectDictSort({2: 5, 5: 1, 4: 3, 1: 1, 0: 1, 9: 2, 8: 2}) вернет:

{0: 1, 1: 1, 5: 1, 8: 2, 9: 2, 4: 3, 2: 5}

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

(обновленный код с retrun new_dct на return new_dict)

avatar
Maxime Chéramy
15 сентября 2018 в 13:37
25

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

vizyourdata
19 ноября 2018 в 20:10
0

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

avatar
mcgag
27 мая 2018 в 17:45
8

Только что изучил соответствующий навык у 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')]
Rubel
4 февраля 2020 в 13:50
0

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

Hermes Morales
4 мая 2020 в 20:14
0

Если вы хотите распечатать его в исходном формате, вы должны сделать: 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)]

mcgag
7 августа 2021 в 03:34
0

@Rubel Дважды проверьте вывод! например [(1.0, 'апельсин'), (500.1, 'яблоко'), (789.0, 'ананас'), (1500.2, 'банан')] сортируются по значениям.

avatar
Bram Vanroy
2 марта 2018 в 16:48
11

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

Когда вы пытаетесь использовать сортировку на итерации, содержащей, например, строки, а также целые числа, 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")
avatar
Vishwanath Rawat
25 мая 2017 в 18:13
16

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

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)
rkochev
19 января 2021 в 12:44
0

Это единственный ответ, который до сих пор работал в python 2.7.

avatar
xiyurui
24 мая 2017 в 03:19
-2

Этот метод не использует лямбда-выражение и хорошо работает на Python 3.6:

 # sort dictionary by value
d = {'a1': 'fsdfds', 'g5': 'aa3432ff', 'ca':'zz23432'}
def getkeybyvalue(d,i):
    for k, v in d.items():
        if v == i:
            return (k)

sortvaluelist = sorted(d.values())

# In >> Python 3.6+ << the INSERTION-ORDER of a dict is preserved. That is,
# when creating a NEW dictionary and filling it 'in sorted order',
# that order will be maintained.
sortresult ={}
for i1 in sortvaluelist:   
    key = getkeybyvalue(d,i1)
    sortresult[key] = i1
print ('=====sort by value=====')
print (sortresult)
print ('=======================')
HDJEMAI
24 мая 2017 в 03:37
3

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

Jean-François Fabre♦
17 мая 2019 в 19:20
1

это очень неэффективное решение с линейным поиском и всем

avatar
Dilettant
10 сентября 2016 в 10:05
78

Начиная с 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 «Компактный и упорядоченный dict» в Python 3.6 теперь мы сможем использовать встроенный dict для поддержания порядка вставки !!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Alex Riley
10 сентября 2016 в 20:15
16

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

Dilettant
10 сентября 2016 в 20:22
0

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

Dimitris Fasarakis Hilliard
10 декабря 2016 в 13:33
0

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

Dilettant
10 декабря 2016 в 13:58
0

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

gerrit
19 декабря 2018 в 17:12
8

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

avatar
arcseldon
5 декабря 2015 в 09:46
110

ОБНОВЛЕНИЕ: 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)])
avatar
ytpillai
31 июля 2015 в 08:08
12

Конечно, помните, что вам нужно использовать 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 или выше

gerrit
19 декабря 2018 в 17:13
0

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

avatar
Scott
20 июня 2015 в 01:44
10

Вот решение с использованием 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')]
avatar
malthe
25 сентября 2014 в 22:56
15

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

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

Suleman Elahi
6 февраля 2020 в 12:15
0

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

malthe
6 февраля 2020 в 13:14
0

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

avatar
Nathaniel Payne
7 апреля 2014 в 04:46
27

Попробуйте следующий подход. Определим словарь 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
Andomar
7 июля 2017 в 19:08
0

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

lb_so
5 июня 2021 в 10:30
0

это не работает в более поздних версиях python, которые не поддерживают распаковку кортежей и где dicts больше не имеют iteritems ()

avatar
Eamonn Kenny
3 марта 2014 в 14:58
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)]
lb_so
5 июня 2021 в 10:32
0

Я не согласен с вашим комментарием о обратной совместимости ... может быть вообще нет оправдания для его сохранения - на самом деле, это может быть откровенно негативным поступком.

avatar
lessthanl0l
13 февраля 2014 в 23:18
4
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
avatar
sweetdream
22 августа 2013 в 08:38
36

В 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

Наслаждайтесь ;-)

avatar
Abhijit
23 марта 2013 в 14:19
6

Для полноты картины я публикую решение с использованием 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)]
avatar
Abhijit
9 марта 2013 в 12:30
21

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

>>> 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)])
Peter Mortensen
3 апреля 2014 в 17:07
7

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

avatar
raton
3 ноября 2012 в 11:07
0

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

x = {"b":4, "a":3, "c":1}
for i in sorted(x.values()):
    print(list(x.keys())[list(x.values()).index(i)])
avatar
Ivan Sas
27 июня 2012 в 15:43
43

Если значения числовые, вы также можете использовать 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)]    
James
28 декабря 2013 в 13:17
0

как насчет того, если ваш словарь >>> x = {'hello': 1, 'python': 5, 'world': 300}

lvc
28 декабря 2013 в 13:58
0

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

avatar
Petr Viktorin
24 января 2012 в 19:28
6

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

avatar
iFail
16 ноября 2011 в 07:32
6

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

import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)
avatar
juhoh
30 октября 2011 в 19:42
7

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

$ 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
avatar
ponty
19 октября 2011 в 06:25
8

Используйте 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)]
avatar
Remi
30 августа 2011 в 00:30
79

Часто бывает очень удобно использовать 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
rowana
7 февраля 2017 в 20:31
0

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

Remi
23 февраля 2017 в 12:31
0

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

avatar
PedroMorgan
8 марта 2011 в 02:06
28

Это код:

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}
avatar
jimifiki
18 ноября 2010 в 14:19
45

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

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

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

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

Dejell
7 января 2014 в 20:54
1

Вы упускаете значение из результата

Ron Klein
21 сентября 2016 в 08:00
0

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

Max
12 января 2019 в 03:19
1

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

avatar
Argun
1 ноября 2010 в 12:16
13
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
Remi
30 августа 2011 в 00:38
2

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

avatar
Nas Banov
5 июля 2010 в 08:01
1434

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

Ну, вообще-то можно выполнить «сортировку по словарным значениям». Недавно мне пришлось сделать это в Code Golf (вопрос о переполнении стека 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])

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

smci
9 декабря 2011 в 21:18
35

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

Izkata
19 августа 2014 в 20:21
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 использует ключи без значений

Eevee
25 июня 2017 в 20:47
22

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

avatar
mykhal
5 июля 2010 в 02:50
170

В последней версии 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)])
Nas Banov
5 июля 2010 в 07:07
5

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

mykhal
5 июля 2010 в 10:56
10

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

JZAU
8 ноября 2013 в 05:12
0

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

CadentOrange
19 ноября 2013 в 09:06
0

@jie d.items() возвращает список пар ключ / значение из словаря, а x является элементом этого кортежа. x[0] будет ключевым, а x[1] будет значением. Поскольку мы собираемся отсортировать значение, мы передаем лямбду x[1].

Boern
31 августа 2017 в 14:28
0

может быть глупый вопрос: x: x[1] - к чему обращается 1? Сама стоимость? Что такое 0 тогда? Ключ?

BallpointBen
10 апреля 2018 в 14:29
1

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

ShadowRanger
4 сентября 2019 в 13:09
2

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

avatar
Mark
13 февраля 2010 в 16:33
987

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

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)]
UsAndRufus
20 февраля 2013 в 10:38
0

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

Claudiu
9 апреля 2015 в 23:08
62

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

dhj
16 ноября 2015 в 16:49
0

@Keyo, разве не должно быть, чтобы он возвращал упорядоченный список ключей (отсортированный по значениям), а не кортежи (k,v)? Вот что я получаю с Python 2.7.10. @Nyxynyx добавьте параметр reverse = True для сортировки в порядке убывания.

Bob Stein
5 февраля 2016 в 17:53
42

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

Dr_Hope
16 июля 2019 в 15:39
5

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

avatar
S.Lott
5 марта 2009 в 01:52
23

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

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]
avatar
user26294
5 марта 2009 в 01:06
101

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

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

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

sorted((value,key) for (key,value) in mydict.items())
John Fouhy
5 марта 2009 в 01:45
10

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

saidimu apale
3 мая 2010 в 05:22
0

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

Jean-François Fabre♦
7 декабря 2017 в 21:21
0

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

avatar
Roberto Bonvallet
5 марта 2009 в 01:05
250

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

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

sorted(d.values())

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

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))
SabreWolfy
18 июня 2012 в 10:04
0

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

Boris
24 апреля 2020 в 19:38
4

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