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)
Другие вопросы по тегам