Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 16, 2019 23:00:11

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

О сортировке словарей

Приветствую!
Посмотрел несколько тем в разделе - судя по всему, даже новичком себя могу назвать только с натяжкой))
Прохожу сейчас один курс по Python, в одной из задач (не уверен, что ссылку можно выкладывать) требовалось считать из файла данные о болезнях по годам и написать функцию, которая будет формировать список словарей {Название болезни: кол-во}, {Название болезни: кол-во} …, но при этом данные в списке должны быть отсортированы по количеству. Долго возился, в результате решил через сбор данных сначала во вспомогательный список {“Болезнь”: название болезни, “Кол-во”: кол-во}, …, потом уже данные из этого списка сортировал и помещал в конечный.
Вопрос такой: можно ли было как-то организовать сортировку самого этого списка напрямую через sort и значения в словарях, если в каждом словаре по одной записи, но ключи этих записей везде разные?
P.S. И заодно немного не в тему: правильно ли я понимаю, что регистрация с почтой outlook на форуме недоступна? Регистрировался еще утром, письмо до сих пор не пришло, днем написал по этому поводу с того же адреса в поддержку - тоже тишина.
P.P.S. После правки сообщения структуры списков в квадратных скобках почему-то перестали отображаться, оставил просто словари в фигурных

Отредактировано Egorro13 (Апрель 17, 2019 00:28:57)

Офлайн

#2 Апрель 17, 2019 02:48:46

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

О сортировке словарей

Egorro13
в одной из задач (не уверен, что ссылку можно выкладывать)
Надо выложить задание, не надо перессказывать его.



Офлайн

#3 Апрель 17, 2019 09:10:01

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

О сортировке словарей

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("Неверный возраст!")

Отредактировано Egorro13 (Апрель 17, 2019 09:22:15)

Офлайн

#4 Апрель 17, 2019 11:46:46

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

О сортировке словарей

Упорядоченный словарь сделать можно через 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}]}
>>>



Офлайн

#5 Апрель 17, 2019 11:55:27

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

О сортировке словарей

Спасибо, насчет сортировки словарей в заголовке - неправильно выразился: уже несколько раз сталкивался с необходимостью сортировать содержимое именно словарей, но так и не разобрался до конца, потому, видимо, и тут на автомате сработало))
Насчет tuple(d.values()) в голову не пришло - на Питон перешел с Явы, еще эти кортежи и структуры в голове не утрамбовались, еще раз благодарю!

Офлайн

#6 Апрель 18, 2019 00:30:19

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

О сортировке словарей

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



Офлайн

#7 Апрель 18, 2019 00:45:31

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

О сортировке словарей

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

Сортировка словаря сейчас выглядит как взятие словаря, взятие всех пар словаря, сортировка пар и создание нового словаря из отсортированных пар. Даже на встроенных словарях это работает.
Да, спасибо, это я вроде более-менее понимаю, хотя успешно сортировать до сих пор получалось (насколько помню) только через sorted(dict.keys()), а уже по отсортированным в нужном порядке ключам получать и значения. Сортировать именно по элементам еще толком не научился - опять же, из-за переучивания не все вещи легко даются.
Что в упор не понимаю - каким образом может осуществляться мгновенный доступ к элементам словарей, в любом случае же нужно как-то найти соответствующий элемент в памяти, а как это может происходить без перебора какого-то “перечня” элементов - не представляю даже примерно))

Офлайн

#8 Апрель 18, 2019 05:17:30

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

О сортировке словарей

Egorro13
Что в упор не понимаю - каким образом может осуществляться мгновенный доступ к элементам словарей
Словарь в питоне - это нагруженное множество. Нагруженное множество - это динамическая структура данных. То есть это простое множество (динамическая структура), где у каждого элемента есть нагрузка. Соответственно, к словарю применяется тот же метод поиска, что и для множества. Строится бинарное дерево и по нему идёт поиск. Для миллиона элементов поиск займёт log2(1000000) = 20 переходов по элементам, а для миллиарда элементов поиск займёт log2(1000000000) = 30 переходов по элементам. Поэтому поиск в словаре равен O(1) - с одинаковой скоростью находишь любой элемент, несмотря на их количество. Конечно, это не точная оценка, а приблизительная. Но для 10, 100, 1000, 1000000, 1000000000 элементов скорость поиска будет похожа на одну и ту же.



Отредактировано py.user.next (Апрель 18, 2019 05:18:08)

Офлайн

#9 Апрель 18, 2019 09:39:49

Egorro13
Зарегистрирован: 2019-04-16
Сообщения: 105
Репутация: +  5  -
Профиль  

О сортировке словарей

py.user.next
Строится бинарное дерево и по нему идёт поиск. Для миллиона элементов поиск займёт log2(1000000) = 20 переходов по элементам, а для миллиарда элементов поиск займёт log2(1000000000) = 30 переходов по элементам. Поэтому поиск в словаре равен O(1) - с одинаковой скоростью находишь любой элемент, несмотря на их количество
Благодарю, теперь вроде что-то складывается в голове, всплывает что-то еще из 90-х, когда первые подходы к программированию пытался делать))

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version