Найти - Пользователи
Полная версия: О сортировке словарей
Начало » Python для новичков » О сортировке словарей
1
Egorro13
Приветствую!
Посмотрел несколько тем в разделе - судя по всему, даже новичком себя могу назвать только с натяжкой))
Прохожу сейчас один курс по Python, в одной из задач (не уверен, что ссылку можно выкладывать) требовалось считать из файла данные о болезнях по годам и написать функцию, которая будет формировать список словарей {Название болезни: кол-во}, {Название болезни: кол-во} …, но при этом данные в списке должны быть отсортированы по количеству. Долго возился, в результате решил через сбор данных сначала во вспомогательный список {“Болезнь”: название болезни, “Кол-во”: кол-во}, …, потом уже данные из этого списка сортировал и помещал в конечный.
Вопрос такой: можно ли было как-то организовать сортировку самого этого списка напрямую через sort и значения в словарях, если в каждом словаре по одной записи, но ключи этих записей везде разные?
P.S. И заодно немного не в тему: правильно ли я понимаю, что регистрация с почтой outlook на форуме недоступна? Регистрировался еще утром, письмо до сих пор не пришло, днем написал по этому поводу с того же адреса в поддержку - тоже тишина.
P.P.S. После правки сообщения структуры списков в квадратных скобках почему-то перестали отображаться, оставил просто словари в фигурных
py.user.next
Egorro13
в одной из задач (не уверен, что ссылку можно выкладывать)
Надо выложить задание, не надо перессказывать его.
Egorro13
py.user.next
Надо выложить задание, не надо перессказывать его.
Задание 8.2.8
Сам фрагмент кода заодно:
     # Формирование списков
    data_year_2_sorted_adult = []
    data_year_2_sorted_children = []
    data_changes_sorted_adult = []
    data_changes_sorted_children = []
    tmp = []
    for rec in data:
        d_class = rec[0]
        value1 = rec[i_year1]
        value2 = rec[i_year2]
        d_change = (value2 - value1) / value1 * 100
        record = dict(theclass=d_class, value=value2, change=d_change,
                      age=rec[-1])
        tmp.append(record)
    for rec in sorted(tmp, key=lambda d: d['value'], reverse=True):
        record = {rec['theclass']: round(rec['value'], ndigits=2)}
        if rec['age'] == ADULTS:
            data_year_2_sorted_adult.append(record)
        elif rec['age'] == CHILDREN:
            data_year_2_sorted_children.append(record)
        else:
            raise NoSuchYearError("Неверный возраст!")
    for rec in sorted(tmp, key=lambda d: d['change'], reverse=True):
        record = {rec['theclass']: round(rec['change'], ndigits=2)}
        if rec['age'] == ADULTS:
            data_changes_sorted_adult.append(record)
        elif rec['age'] == CHILDREN:
            data_changes_sorted_children.append(record)
        else:
            raise NoSuchYearError("Неверный возраст!")
py.user.next
Упорядоченный словарь сделать можно через OrderedDict()
  
>>> import json
>>> import collections
>>> 
>>> d = collections.OrderedDict()
>>> d['c'] = 3
>>> d['b'] = 2
>>> d['a'] = 1
>>> 
>>> json.dumps(d)
'{"c": 3, "b": 2, "a": 1}'
>>> 
Это чтобы JSON-файл делать именно в том виде, который указан. В обычном словаре в недавних версиях питона строковые ключи могли располагаться в произвольном порядке, поэтому даже если пишешь ‘c’ ‘a’, словарь мог получаться ‘a’ ‘c’. Поэтому используется OrderedDict() - он гарантирует первоначальный порядок.

Дальше по заданию тебе нужно сортировать не словари, а списки словарей по значениям из словарей.
  
>>> dct = {'x' : [{'a': 4},
...               {'b': 3},
...               {'c': 2},
...               {'d': 1}]}
>>> 
>>> 
>>> dct
{'x': [{'a': 4}, {'b': 3}, {'c': 2}, {'d': 1}]}
>>> 
>>> dct['x'].sort(key=lambda d: tuple(d.values())[0])
>>> dct
{'x': [{'d': 1}, {'c': 2}, {'b': 3}, {'a': 4}]}
>>>
Egorro13
Спасибо, насчет сортировки словарей в заголовке - неправильно выразился: уже несколько раз сталкивался с необходимостью сортировать содержимое именно словарей, но так и не разобрался до конца, потому, видимо, и тут на автомате сработало))
Насчет tuple(d.values()) в голову не пришло - на Питон перешел с Явы, еще эти кортежи и структуры в голове не утрамбовались, еще раз благодарю!
py.user.next
Egorro13
уже несколько раз сталкивался с необходимостью сортировать содержимое именно словарей, но так и не разобрался до конца
Словари не имеют порядка, так как основное их предазначение - быстрый доступ вне зависимости от количества элементов в словаре. То есть хоть при десяти элементах, хоть при миллионе элементов, доступ к каждому элементу должен происходить мнгновенно, без перебора всех элементов. Вот из-за этого там нет порядка. Хотя сейчас словари в питоне сделали упорядоченными (по времени добавления элементов в словарь), не нарушив главного свойства - быстрого поиска элемента в словаре при любом их количестве.

Сортировка словаря сейчас выглядит как взятие словаря, взятие всех пар словаря, сортировка пар и создание нового словаря из отсортированных пар. Даже на встроенных словарях это работает.
  
>>> d = {'a': 4, 'b': 3, 'c': 2, 'd': 1}
>>> 
>>> out = dict(sorted(d.items(), key=lambda i: i[1]))
>>> out
{'d': 1, 'c': 2, 'b': 3, 'a': 4}
>>> 
>>> for i, j in zip(d, out):
...   print('d:', i, '->', d[i], 'out:', j, '->', out[j]) 
... 
d: a -> 4 out: d -> 1
d: b -> 3 out: c -> 2
d: c -> 2 out: b -> 3
d: d -> 1 out: a -> 4
>>>
Egorro13
py.user.next
Словари не имеют порядка, так как основное их предазначение - быстрый доступ вне зависимости от количества элементов в словаре. То есть хоть при десяти элементах, хоть при миллионе элементов, доступ к каждому элементу должен происходить мнгновенно, без перебора всех элементов. Вот из-за этого там нет порядка. Хотя сейчас словари в питоне сделали упорядоченными (по времени добавления элементов в словарь), не нарушив главного свойства - быстрого поиска элемента в словаре при любом их количестве.

Сортировка словаря сейчас выглядит как взятие словаря, взятие всех пар словаря, сортировка пар и создание нового словаря из отсортированных пар. Даже на встроенных словарях это работает.
Да, спасибо, это я вроде более-менее понимаю, хотя успешно сортировать до сих пор получалось (насколько помню) только через sorted(dict.keys()), а уже по отсортированным в нужном порядке ключам получать и значения. Сортировать именно по элементам еще толком не научился - опять же, из-за переучивания не все вещи легко даются.
Что в упор не понимаю - каким образом может осуществляться мгновенный доступ к элементам словарей, в любом случае же нужно как-то найти соответствующий элемент в памяти, а как это может происходить без перебора какого-то “перечня” элементов - не представляю даже примерно))
py.user.next
Egorro13
Что в упор не понимаю - каким образом может осуществляться мгновенный доступ к элементам словарей
Словарь в питоне - это нагруженное множество. Нагруженное множество - это динамическая структура данных. То есть это простое множество (динамическая структура), где у каждого элемента есть нагрузка. Соответственно, к словарю применяется тот же метод поиска, что и для множества. Строится бинарное дерево и по нему идёт поиск. Для миллиона элементов поиск займёт log2(1000000) = 20 переходов по элементам, а для миллиарда элементов поиск займёт log2(1000000000) = 30 переходов по элементам. Поэтому поиск в словаре равен O(1) - с одинаковой скоростью находишь любой элемент, несмотря на их количество. Конечно, это не точная оценка, а приблизительная. Но для 10, 100, 1000, 1000000, 1000000000 элементов скорость поиска будет похожа на одну и ту же.
Egorro13
py.user.next
Строится бинарное дерево и по нему идёт поиск. Для миллиона элементов поиск займёт log2(1000000) = 20 переходов по элементам, а для миллиарда элементов поиск займёт log2(1000000000) = 30 переходов по элементам. Поэтому поиск в словаре равен O(1) - с одинаковой скоростью находишь любой элемент, несмотря на их количество
Благодарю, теперь вроде что-то складывается в голове, всплывает что-то еще из 90-х, когда первые подходы к программированию пытался делать))
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB