python - упорядоченный - отсортировать список участников по алфавиту




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

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

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

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 Заклинатель, как напомнил Раймонд Хеттингер во время обсуждения.

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

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

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


Проще, чем: 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]

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


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

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

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

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


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

Вы можете использовать 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)])

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

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


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

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

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


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

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]

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

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 с исходным словарем.

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


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

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

sorted(d.values())

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

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

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

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

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


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

Например,

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(a_dictionary.values())

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


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

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

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

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


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

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

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

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

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

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


Это код:

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}

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

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

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

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

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

      return _sorted

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




dictionary