使用itertools.groupby按二进制1的个数分组结果不符预期
问题分析与解决方案
为什么itertools.groupby会丢失数据?
itertools.groupby的核心逻辑是仅对相邻且分组键(key)相同的元素进行分组,它不会自动全局聚合所有同key的元素。
你直接使用未排序的0-7序列时,各元素的二进制1的个数分布是分散的:
- 0(key=0)→ 1(key=1)→ 2(key=1)→ 3(key=2)→ 4(key=1)→ 5(key=2)→ 6(key=2)→7(key=3)
同key的元素(如1、2、4)并非连续排列,groupby会生成多个离散的组:(1, [1,2])、(1, [4]),当你将这些结果转成字典时,后出现的同key组会覆盖之前的,最终每个key只保留最后一次出现的组,这就是你看到部分数字丢失的原因。
基于itertools的生成器式解决方案
要实现全局分组,必须先按分组key对原序列排序,让同key元素连续排列,再用groupby处理。以下是完全基于生成器的实现:
代码示例
import itertools def group_by_bit_count(nums): # 先按二进制中1的个数排序,确保同key元素连续 sorted_nums = sorted(nums, key=lambda x: bin(x).count('1')) # 惰性返回分组结果,每个group是生成器 yield from itertools.groupby(sorted_nums, key=lambda x: bin(x).count('1')) # 测试0-7的情况 result = dict((k, list(g)) for k, g in group_by_bit_count(range(8))) print(result) # 输出:{0: [0], 1: [1, 2, 4], 2: [3, 5, 6], 3: [7]} # 惰性遍历(无需提前生成所有列表) for key, group in group_by_bit_count(range(17)): print(f"{key}: {list(group)}")
如果追求极致惰性,也可以将排序后的序列转为生成器(不过sorted本身返回列表,对于超大序列可考虑外部排序,但itertools无内置排序工具)。上述方案中,除排序步骤外,分组过程完全是惰性的,符合生成器式要求。
内容的提问来源于stack exchange,提问作者tBuLi
相关产品推荐
相关产品推荐

