Объяснить работу defaultdict

Пытаюсь с помощью defaultdict группировать данные, благодаря свойству уникальности ключей в словаре. Есть переменная со списком кортежей: request = [(1, '[email protected]'),(2, '[email protected]'),(3, '[email protected]'),(4, '[email protected]'),(5, '[email protected]')]. Я осуществляю группировку по email, предварительно переводя его в нижний регистр таким образом:

players = defaultdict(list)
{players[_i[1].lower()].append(_i[0]) for _i in tqdm.tqdm(request) if _i[0] not in players[_i[1]]}

По моим ожиданиям ответ должен получиться такой:

{
'[email protected]': [1, 2], 
'[email protected]': [3], 
'[email protected]': [4, 5]
}

Но почему-то в результате получаю такое:

{
'[email protected]': [1, 2], 
'[email protected]': [], 
'[email protected]': [3], 
'[email protected]': [4, 5], 
'[email protected]': []
}

Можете объяснить, почему?

P.S. tqdm сторонняя библиотека для визуализации процесса выполнения прохода по списку.


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

Автор решения: alex

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

players = defaultdict(list)
{players[_i[1].lower()].append(_i[0]) for _i in tqdm.tqdm(request) if _i[0] not in players[_i[1]]}

Давайте для начала перепишем пример. чтобы мне было проще указать место.

1for _i in tqdm.tqdm(request):
2    if _i[0] not in players[_i[1]]:
3        players[_i[1].lower()].append(_i[0])

во второй строке в условии идет получение значения по ключу players[_i[1]]. в этот самый момент добавляется запись. если ключа нет. т.е. вместо получения стандартной ошибки KeyError. а так как тут нет перевода в нижний регистр то вы и получаете то что получаете.

players = defaultdict(list)
{players[_i[1].lower()].append(_i[0]) for _i in tqdm.tqdm(request) if _i[0] not in players[_i[1].lower()]}

можно убрать проверку уникальности

players = defaultdict(set)
{players[_i[1].lower()].add(_i[0]) for _i in tqdm.tqdm(request)}
→ Ссылка