为何itertools.groupby转为dict后,取值得到空列表?
为什么itertools.groupby转成dict后遍历分组会得到空列表?
核心原因:groupby返回的是绑定原序列的迭代器,而非持久化容器
itertools.groupby的工作逻辑是实时遍历原序列、按需生成分组,它返回的分组生成器(代码里的v_gen)并不是独立存储分组数据的容器,而是和原序列的迭代位置绑定的一次性迭代器。
当你执行dict(groupby(raw, key=lambda x: x["age"]))时,Python会完整迭代一遍groupby对象,把所有(key, 生成器)键值对存入字典。但这个过程中,原序列的迭代指针已经走到了末尾——每个分组生成器其实只是"指向"原序列中对应分组的位置,当原序列被遍历完后,这些生成器再被调用时就没有元素可以返回了,所以A部分执行list(grouped[v])会得到空列表。
而B部分直接遍历groupby对象时,每拿到一个分组生成器就立刻用list()消费它,这时候原序列的迭代指针还停留在对应分组的位置,所以能正常取出元素。
解决办法:构造字典时提前把分组元素转为列表
如果需要把分组结果持久化到字典里,要在生成字典的过程中就把每个分组的生成器转为列表(或其他容器),而不是直接存储生成器本身:
from itertools import groupby raw = [ {"name": "A", "age": 20}, {"name": "A", "age": 20}, {"name": "A", "age": 21}, {"name": "A", "age": 21}, ] # 提前将分组生成器转为列表存入字典 grouped = {key: list(gen) for key, gen in groupby(raw, key=lambda x: x["age"])} for v in grouped: print(grouped[v])
执行这段代码后,输出就会符合你的期望:
[{'name': 'A', 'age': 20}, {'name': 'A', 'age': 20}] [{'name': 'A', 'age': 21}, {'name': 'A', 'age': 21}]
额外注意:groupby要求原序列按分组key排序
groupby只会把连续相同key的元素归为一组,如果原序列没有按分组key排序,可能会得到不符合预期的分组结果。如果需要全局按key分组,记得先排序:
raw_sorted = sorted(raw, key=lambda x: x["age"]) grouped = {key: list(gen) for key, gen in groupby(raw_sorted, key=lambda x: x["age"])}
内容的提问来源于stack exchange,提问作者ShIRann
相关产品推荐
相关产品推荐

