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





алфавиту сортировка (25)


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

sorted(iterable[, cmp[, key[, reverse]]])

Таким образом, вы можете использовать:

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

Перейдите по этой ссылке для получения дополнительной информации о отсортированной функции: https://docs.python.org/2/library/functions.html#sorted

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

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

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




Итерируйте через 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



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




Я придумал этот,

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

Для Python 3.x: x.items() заменяет iteritems() .

>>> sorted_x
{0: 0, 1: 2, 2: 1, 3: 4, 4: 3}

Или попробуйте с collections.OrderedDict !

x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
from collections import OrderedDict

od1 = OrderedDict(sorted(x.items(), key=lambda t: t[1]))



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

Хорошие новости, поэтому исходный пример использования 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 в целом будет тщательно проверять, если это выдержит испытание временем и какие будут следующие шаги.

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

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

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

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

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

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

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

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

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

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

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

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

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




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

sorted(a_dictionary.values())

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




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

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

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

a) I don't know about how well it works 

а также

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)
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 или выше




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

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)

Еще один способ - использовать функцию labmda

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



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



ОБНОВЛЕНИЕ: 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)])



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

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]



Это возвращает список пар ключ-значение в словаре, отсортированный по значению от наивысшего до самого низкого:

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

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

sorted(d.items(), reverse=True)

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

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




Данный словарь

e = {1:39, 4:34, 7:110, 2:87}

Сортировка

sred = sorted(e.items(), key=lambda value: value[1])

Результат

[(4, 34), (1, 39), (2, 87), (7, 110)]

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

Надеюсь, это поможет!




Попробуйте следующий подход. Определим словарь под названием 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



В последнем 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)])



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

Например,

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_by_value = sorted(x.items(), key=lambda kv: kv[1])



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

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

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




Это код:

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}



В значительной степени то же, что и ответ Хэнка Гей;

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

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

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




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

Это позволяет создавать пары (значение, ключ), используя zip (): pairs = 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')]



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

from collections import Counter

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


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



Используйте 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)]



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

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



Проще, чем: sorted(dict1, key=dict1.get)

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

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




Он может выглядеть более чистым с использованием ключа вместо cmp:

newlist = sorted(list_to_be_sorted, key=lambda k: k['name']) 

или, как предложили JFSebastian и другие,

from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name')) 

Для полноты (как указано в комментариях fitzgeraldsteele), добавьте reverse=True для сортировки по убыванию

newlist = sorted(l, key=itemgetter('name'), reverse=True)




python sorting dictionary