Python itertools.groupby дает неожиданные результаты при сортировке по двоичному представлению
Я пытаюсь решить простую проблему, используяitertools.groupby
: сгруппировать числа из0
к7
по количеству1
в их двоичном представлении. Итак, я хочу создать отображение
{0: [0], 1: [1, 2, 4], 2: [3, 5, 6], 3: [7]}
Но вот что я получаю отgroupby
:
>>> from itertools import groupby
>>> def key(i):
... print(i, bin(i), bin(i).count('1'))
... return bin(i).count('1')
>>> groups = {k: list(v) for k, v in groupby(range(8), key=key)}
0 0b0 0
1 0b1 1
2 0b10 1
3 0b11 2
4 0b100 1
5 0b101 2
6 0b110 2
7 0b111 3
>>> groups
{0: [0], 1: [4], 2: [5, 6], 3: [7]}
Результат меня совершенно сбил с толку. Операторы печати показывают, что отдельные вызовы ключевой функции ведут себя так, как ожидалось, и все же я теряю числа.1, 2, 3
по пути. Становится еще хуже, когда я использую, например, 16:
>>> {k: list(v) for k, v in groupby(range(16), key=lambda i: bin(i).count('1'))}
{0: [0], 1: [8], 2: [12], 3: [13, 14], 4: [15]}
Я надеюсь понять, как groupby приходит к такому результату, и узнать, есть ли способ решить эту проблему с помощью . (Я не ищу решения проблемы как таковой, только для причудливого решения генератора, использующего, например,itertools
.)
(Я пробовал это в python 3.9 и 3.10, поэтому я совершенно уверен, что это не ошибка)
1 ответ
Если вы хотите использовать, вам нужно сначала отсортировать список ввода.
groups = {k: list(v) for k, v in groupby(sorted(range(8), key=key), key=key)}
Ваш генератор отбрасывает старые записи, когда та же группа встречается позже.
Вы уже используетеdict
поэтому вам не нужно использоватьgroupby
совсем
d = defaultdict(list)
for i in range(8):
d[key(i)].append(i)