Python groupby 为什么会出现两个同名分组?
一份名单里,“研发”出现了两次。直接使用 itertools.groupby,为什么也会得到两个“研发”分组?先看一个可直接运行的样例。
1. 同名分组出现两次
from itertools import groupby
rows = [("研发", "小王"), ("产品", "小李"), ("研发", "小周")]
for team, members in groupby(rows, key=lambda row: row[0]):
print(team, [name for _, name in members])
实际结果是:
研发 ['小王']
产品 ['小李']
研发 ['小周']
groupby 按相邻元素的键变化划分组。名单从“研发”变为“产品”,再变回“研发”,所以出现三组。后面的同名键不会自动并回前面的组。Python 官方 itertools 文档对这个行为有明确说明。
如果需要表示输入中连续的片段,这个结果就是需要的结果,不必排序。
2. 想按部门合并时,先让同名部门相邻
在接着上例执行时,可以对同一个键排序:
ordered = sorted(rows, key=lambda row: row[0])
for team, members in groupby(ordered, key=lambda row: row[0]):
print(team, [name for _, name in members])
本样例得到:
产品 ['小李']
研发 ['小王', '小周']
这里使用 sorted 返回新的列表,原始 rows 的顺序保持不变。排序键与分组键一致,才符合这段代码“按部门合并”的目的。不要把例子中的中文排序顺序当成业务规定;有自定义展示顺序时,应明确写出排序规则。
groupby 返回的组本身是迭代器。若准备稍后再处理某一组,应在当前轮用 list(members) 保存它,不要先收集组迭代器,最后才统一消费。
3. 不想为了聚合排序,可以直接用字典
如果目标只是按部门收集成员,下面的写法更直接:
from collections import defaultdict
groups = defaultdict(list)
for team, name in rows:
groups[team].append(name)
print(dict(groups))
本样例得到:
{'研发': ['小王', '小周'], '产品': ['小李']}
这一版按原始输入顺序向各部门追加成员,但会把成员保存在列表里。数据很大时,需要考虑保存完整分组的内存成本;本文没有做性能或内存基准测试。
4. 先确认需求,再选写法
要保留连续片段,就直接使用 groupby;要把同键记录收在一起,可以先按同一个键排序,也可以用字典累计。不要仅凭函数名判断两种写法等价。
本次教学数据为独立构造的名单,不来自真实人员记录。在本机 Python 3.9.6 中,检查了相邻分组的键与数量、排序后的合并、字典聚合、原始输入保持不变、空输入和相邻重复,共七项断言。
官方参考:docs.python.org/3/library/itertools.html#itertools.groupby。
本文由 AI 辅助整理,示例已在本机实际执行。
- 点赞
- 收藏
- 关注作者
评论(0)