Манипуляции со словарями, Python

Написал вот такой код:

from collections import defaultdict
import datetime


slovar = [{'date': datetime.date(2022, 8, 20), 'type': 'WRITE'},
          {'date': datetime.date(2022, 8, 18), 'type': 'READ'},
          {'date': datetime.date(2022, 8, 18), 'type': 'WRITE'}]

historic = defaultdict(list)

for i in slovar:
    date, type = i['date'], i['type']
    historic[date].append(type)

print(dict(historic))
>>>{datetime.date(2022, 8, 20): ['WRITE'], datetime.date(2022, 8, 18): ['READ', 'WRITE']}

Не могу сообразить, как привести его к такому вот виду(т.е., чтобы словари были внутри словаря + сортировка по дате + подсчет READ и WRITE и привязка их к дате):

>>>{{datetime.date(2022, 8, 18): {'READ': 1, 'WRITE': 1}, datetime.date(2022, 8, 20): {'WRITE': 1}}

Помогите, пожалуйста


Ответы (2 шт):

Автор решения: Stanislav Volodarskiy

Сортировка

Сортировать словарь я бы не стал. Вы всегда можете его обойти без предварительной сортировки в нужном порядке:

# обработка ключей в хронологическом порядке
for k in sorted(historic.keys()):
    pass

Или:

# обработка ключей и значений в хронологическом порядке
for k, v in sorted(historic.items()):
    pass

Но если вам всё-таки нужен именно сортированный словарь, то добавьте к любому рецепту ниже немного сортировки:

historic = dict(sorted(historic.items()))

Построение словаря

collections.Counter:

from collections import defaultdict, Counter


historic = defaultdict(Counter)
for i in slovar:
    historic[i['date']][i['type']] += 1
defaultdict(<class 'collections.Counter'>,
            {datetime.date(2022, 8, 18): Counter({'READ': 1, 'WRITE': 1}),
             datetime.date(2022, 8, 20): Counter({'WRITE': 1})})

Если хочется обойтись без Counter, вариант с обычными словарями:

from collections import defaultdict


historic = defaultdict(dict)
for i in slovar:
    type_ = i['type']
    d = historic[i['date']]
    d.setdefault(type_, 0)
    d[type_] += 1
defaultdict(<class 'dict'>,
            {datetime.date(2022, 8, 18): {'READ': 1, 'WRITE': 1},
             datetime.date(2022, 8, 20): {'WRITE': 1}})

И вариант полностью на обычных словарях:

historic = {}
for i in slovar:
    type_ = i['type']
    d = historic.setdefault(i['date'], {})
    d.setdefault(type_, 0)
    d[type_] += 1
{datetime.date(2022, 8, 18): {'READ': 1, 'WRITE': 1},
 datetime.date(2022, 8, 20): {'WRITE': 1}}
→ Ссылка
Автор решения: Lecron
from collections import defaultdict, Counter
import datetime


slovar = [{'date': datetime.date(2022, 8, 20), 'type': 'WRITE'},
          {'date': datetime.date(2022, 8, 18), 'type': 'READ'},
          {'date': datetime.date(2022, 8, 18), 'type': 'WRITE'}]

historic = defaultdict(Counter)

for i in slovar:
    date, type_ = i.values()
    historic[date][type_] += 1

historic_sort = {d: dict(historic[d]) for d in sorted(historic.keys())}
print(historic_sort)

Но вообще не дело полагаться на порядок следования ключей в словаре.

→ Ссылка