
本文介绍如何利用 Python 的 itertools.groupby 对已排序的属性行数据进行智能分组,将相同属性前缀(如 attr1、attr2)的连续行聚合成子列表,适用于千行级库文件解析场景。
本文介绍如何利用 python 的 `itertools.groupby` 对已排序的属性行数据进行智能分组,将相同属性前缀(如 attr1、attr2)的连续行聚合成子列表,适用于千行级库文件解析场景。
在处理结构化文本库文件(如配置项、属性定义表)时,常需将具有相同逻辑前缀(例如 attr1、attr2)的相邻行归为一组,形成嵌套列表结构。原始代码试图手动遍历并维护临时分组列表,但逻辑存在关键缺陷:它错误地将非匹配行(else 分支)也纳入分组,且未正确识别“属性切换点”——即当前行前缀与上一行不同时才应新建子列表。
更可靠、简洁且符合 Python 惯用法的方案是使用 itertools.groupby。该函数专为对已排序序列按键分组而设计,恰好匹配本例中“相同属性前缀连续出现”的输入特征(示例输入已按 attr1/attr2/attr3 有序排列)。
以下是完整可运行的解决方案:
from itertools import groupby
def read_data(filename):
"""逐行读取文件,跳过空行并去除首尾空白"""
with open(filename, 'r', encoding='utf-8') as file:
for line in file:
stripped = line.strip()
if stripped: # 忽略空行
yield stripped
def grouping_key(line):
"""提取每行第一个单词作为分组依据(如 'attr1')"""
return line.split()[0]
# 执行分组
groups = []
for key, group_iter in groupby(read_data("library.txt"), grouping_key):
groups.append(list(group_iter))
print(groups)
# 输出:[['attr1 apple 1', 'attr1 banana 2'], ['attr2 grapes 1', 'attr2 oranges 2'], ['attr3 watermelon 0']]
✅ 优势说明:
- 健壮性高:自动跳过空行,避免 split()[0] 索引错误;
- 内存友好:read_data() 使用生成器,适合处理千行甚至万行大文件;
- 逻辑清晰:groupby 内部自动检测键变化点,无需手动维护 current_group 状态;
- 可扩展性强:只需修改 grouping_key 函数即可适配其他分组规则(如按前两个词、正则提取等)。
⚠️ 重要注意事项:
- groupby 要求输入序列必须按分组键有序。若源文件中 attr2 行出现在 attr1 行之后又混入 attr1 行,则结果会错误拆分。此时需先排序:sorted(read_data(...), key=grouping_key)(但会失去原始顺序,慎用);
- 确保文件编码兼容(推荐显式指定 encoding='utf-8');
- 若输入含不规范格式(如某行无空格导致 split() 返回空列表),建议在 grouping_key 中增加容错处理,例如:
def grouping_key(line): parts = line.strip().split() return parts[0] if parts else ""
此方法以声明式风格替代了易错的手动状态管理,显著提升代码可读性与维护性,是文本分组任务的标准实践。










