Подтвердить что ты не робот

Сортировочный словарь python 3

Я работаю над python 3.2.2. Ломать голову более 3 часов, чтобы отсортировать словарь по этим клавишам. Мне удалось сделать его отсортированным списком с двумя членами аргумента, но в конце он не может сделать его отсортированным.

Вот что я понял:

myDic={10: 'b', 3:'a', 5:'c'}
sorted_list=sorted(myDic.items(), key=lambda x: x[0])

Но независимо от того, что я не могу сделать из этого отсортированного списка. Как мне это сделать? Спасибо!

4b9b3361

Ответ 1

dict не сохраняет порядок своих элементов. Что вам нужно, это OrderedDict: http://docs.python.org/library/collections.html#collections.OrderedDict

изменить

Пример использования:

>>> from collections import OrderedDict
>>> a = {'foo': 1, 'bar': 2}
>>> a
{'foo': 1, 'bar': 2}
>>> b = OrderedDict(sorted(a.items()))
>>> b
OrderedDict([('bar', 2), ('foo', 1)])
>>> b['foo']
1
>>> b['bar']
2

Ответ 2

Я не думаю, что вы хотите заказать OrderDict. Похоже, вы предпочтете SortedDict, который является типом, который поддерживает свои ключи в отсортированном порядке. Модуль sortedcontainers предоставляет именно такой тип данных. Он написан в версиях pure-Python, fast-as-C, имеет 100% охват и часы стресса.

Установка с помощью pp легко:

pip install sortedcontainers

Обратите внимание, что если вы не можете pip install, вы можете просто вытащить исходные файлы из хранилища с открытым исходным кодом.

Тогда вы код просто:

from sortedcontainers import SortedDict
myDic = SortedDict({10: 'b', 3:'a', 5:'c'})
sorted_list = list(myDic.keys())

Модуль sortedcontainers также поддерживает сравнение производительности с другими популярными реализациями.

Ответ 3

Python обычный dicts не может быть создан для предоставления ключей/элементов в любом конкретном порядке. Для этого вы можете использовать тип OrderedDict из модуля collections. Обратите внимание, что тип OrderedDict просто хранит запись порядка вставки. Вам нужно будет отсортировать записи до инициализации словаря, если вы хотите, чтобы последующие представления/итераторы возвращали элементы в порядке каждый раз. Например:

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sorted_list=sorted(myDic.items(), key=lambda x: x[0])
>>> myOrdDic = OrderedDict(sorted_list)
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> myOrdDic[7] = 'd'
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b'), (7, 'd')]

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

Изменить: Итак, если объект сортировки данных просто для его печати в порядке, в формате, напоминающем объект python dict, должно быть достаточно следующего типа:

def pprint_dict(d):
    strings = []
    for k in sorted(d.iterkeys()):
        strings.append("%d: '%s'" % (k, d[k]))
    return '{' + ', '.join(strings) + '}'

Обратите внимание, что эта функция не является гибкой w/r/t для типов пар ключей, значений (т.е. он ожидает, что ключи будут целыми и соответствующие значения будут строками). Если вам нужна большая гибкость, используйте вместо этого strings.append("%s: %s" % (repr(k), repr(d[k]))).

Ответ 4

Современное и быстрое решение для Python 3.7. Может также работать в некоторых интерпретаторах Python 3.6.

TL;DR

Для сортировки словаря по ключам используйте:

sorted_dict = {k: disordered[k] for k in sorted(disordered)}

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

Прокомментируйте принятый ответ

Пример в принятом ответе вместо перебора только ключей - с параметром key sorted() или поведением по умолчанию для итерации - перебирает кортежи (key, value), что на удивление оказывается намного медленнее, чем сравнение ключей только и доступ к элементам словаря в понимании списка.

Как сортировать по ключу в Python 3.7

Большое изменение в Python 3.7 заключается в том, что словари теперь упорядочены по умолчанию.

  • Вы можете генерировать отсортированные слова, используя их.
  • Использование OrderedDict все еще может быть предпочтительным для совместимости.
  • Не используйте sorted(d.items()) без key.

Увидеть:

disordered = {10: 'b', 3: 'a', 5: 'c'}

# sort keys, then get values from original - fast
sorted_dict = {k: disordered[k] for k in sorted(disordered)}

# key = itemgetter - slower
from operator import itemgetter
key = itemgetter(0)
sorted_dict = {k: v for k, v in sorted(disordered.items(), key=key)}

# key = lambda - the slowest
key = lambda item: item[0]
sorted_dict = {k: v for k in sorted(disordered.items(), key=key)} 

Сроки результаты:

Best for {k: d[k] for k in sorted(d)}: 7.507327548999456
Best for {k: v for k, v in sorted(d.items(), key=key_getter)}: 12.031082626002899
Best for {k: v for k, v in sorted(d.items(), key=key_lambda)}: 14.22885995300021

Best for dict(sorted(d.items(), key=key_getter)): 11.209122000000207
Best for dict(sorted(d.items(), key=key_lambda)): 13.289728325995384
Best for dict(sorted(d.items())): 14.231471302999125

Best for OrderedDict(sorted(d.items(), key=key_getter)): 16.609151654003654
Best for OrderedDict(sorted(d.items(), key=key_lambda)): 18.52622927199991
Best for OrderedDict(sorted(d.items())): 19.436101284998585

Тестовый код:

from timeit import repeat

setup_code = """
from operator import itemgetter
from collections import OrderedDict
import random
random.seed(0)
d = {i: chr(i) for i in [random.randint(0, 120) for repeat in range(120)]}
key_getter = itemgetter(0)
key_lambda = lambda item: item[0]
"""

cases = [
    # fast
    '{k: d[k] for k in sorted(d)}',
    '{k: v for k, v in sorted(d.items(), key=key_getter)}',
    '{k: v for k, v in sorted(d.items(), key=key_lambda)}',
    # slower
    'dict(sorted(d.items(), key=key_getter))',
    'dict(sorted(d.items(), key=key_lambda))',
    'dict(sorted(d.items()))',
    # the slowest 
    'OrderedDict(sorted(d.items(), key=key_getter))',
    'OrderedDict(sorted(d.items(), key=key_lambda))',
    'OrderedDict(sorted(d.items()))',
]

for code in cases:
    times = repeat(code, setup=setup_code, repeat=3)
    print(f"Best for {code}: {min(times)}")

Ответ 5

Любое современное решение этой проблемы? Я работал вокруг:

    order = sorted([ job['priority'] for job in self.joblist ])
    sorted_joblist = []
    while order:
        min_priority = min(order)
        for job in self.joblist:
            if job['priority'] == min_priority:
                sorted_joblist += [ job ]
                order.remove(min_priority)
    self.joblist = sorted_joblist

Список заданий форматируется как: joblist = [{'priority': 3, 'name': 'foo',...}, {'priority': 1, 'name': 'bar',...}]

  • В основном я создаю список (порядок) со всеми элементами, по которым я хочу сортировать dict
  • Затем я повторяю этот список и dict, когда я нахожу элемент на dict, я отправляю его в новый dict и удаляю элемент из "order".

Кажется, работает, но я полагаю, что есть лучшие решения.

Ответ 6

С Python 3.7 я мог бы сделать это:

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(dict(sortDic))
{3:'a', 5:'c', 10: 'b'}

Если вы хотите список кортежей:

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(sortDic)
[(3, 'a'), (5, 'c'), (10, 'b')]

Ответ 7

Мне нравится python numpy для такого рода вещей! например:

r=readData()
nsorted = np.lexsort((r.calls, r.slow_requests, r.very_slow_requests, r.stalled_requests))

У меня есть пример импорта CSV-данных в numpy и упорядочение по приоритетам столбцов. https://github.com/unixunion/toolbox/blob/master/python/csv-numpy.py

Кеган

Ответ 8

Возможно, это не так хорошо, но я понял это:

def order_dic(dic):
    ordered_dic={}
    key_ls=sorted(dic.keys())
    for key in key_ls:
        ordered_dic[key]=dic[key]
    return ordered_dic

Ответ 9

Принятый ответ определенно работает, но как-то упускает важный момент.

ОП запрашивает словарь, отсортированный по его keys это просто OrderedDict а не то, что делает OrderedDict.

OrderedDict поддерживает содержание словаря в порядке вставки. Первый элемент вставлен, второй элемент вставлен и т.д.

>>> d = OrderedDict()
>>> d['foo'] = 1
>>> d['bar'] = 2
>>> d
OrderedDict([('foo', 1), ('bar', 2)])

>>> d = OrderedDict()
>>> d['bar'] = 2
>>> d['foo'] = 1
>>> d
OrderedDict([('bar', 2), ('foo', 1)])

Поэтому я не смогу отсортировать словарь на месте, а просто создать новый словарь, в котором порядок вставки соответствует порядку ключа. Это явно указано в принятом ответе, где новый словарь - b.

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

>>> d = OrderedDict({'foo': 5, 'bar': 8})
>>> d
OrderedDict([('foo', 5), ('bar', 8)])
>>> d['alpha'] = 2
>>> d
OrderedDict([('foo', 5), ('bar', 8), ('alpha', 2)])

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

Это означает, что это эквивалентно делать:

>>> d = {'foo': 5, 'bar': 8}
>>> for k,v in d.iteritems(): print k, v

по гипотетическому, отсортированному по ключевому словарю или:

>>> d = {'foo': 5, 'bar': 8}
>>> for k, v in iter((k, d[k]) for k in sorted(d.keys())): print k, v

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

Ответ 10

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

>>> myDic
{10: 'b', 3: 'a', 5: 'c'}
>>> sorted(myDic.items())
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> print(dict(myDic.items()))
{10: 'b', 3: 'a', 5: 'c'}