
本文介绍如何使用纯 python 读取文本文件,按首列键名前缀(如 apple_1、apple_2)自动识别逻辑组,并对每组内所有相邻行(以 `_1` 为组起始标志)的数值列求平均值,最终输出简洁汇总结果。
在处理结构化但非标准的文本数据时(例如实验记录、日志摘要或批量采集结果),常需对“逻辑连续行”进行聚合——而非简单按固定行数分组。本例中,数据以 xxx_1、xxx_2、xxx_3 等形式隐式定义组边界:每个 _1 表示新组开始,其后连续的同前缀行(如 apple_2、apple_3)属于同一组;组内所有数值列(第2–4列)需逐列求平均,前缀(如 apple)作为输出标识。
以下为完整可运行解决方案(无需 Pandas 或 NumPy,仅依赖内置模块):
def averages(lst, n):
"""生成器:对列表中每个元素除以 n,返回浮点平均值"""
for v in lst:
yield v / n
def dump(prev, cols, count):
"""输出当前组结果:前缀 + 各列平均值(保留小数)"""
if prev:
print(prev, *averages(cols, count))
# 主逻辑:逐行解析,动态累积并触发输出
with open("example.txt") as data:
cols = [] # 存储当前组所有数值列的累加和(长度=列数)
count = 0 # 当前组已处理行数
prev = None # 当前组前缀(如 'apple')
for line in data:
line = line.strip()
if not line: # 跳过空行
continue
parts = line.split()
key, *values = parts
nums = list(map(float, values)) # 强制转 float,支持小数输入
# 拆分键:apple_2 → ('apple', '2')
fruit, suffix = key.rsplit("_", 1)
if suffix == "1":
# 遇到新组起点:先输出上一组结果(如有),再重置状态
dump(prev, cols, count)
prev = fruit
cols = nums.copy() # 初始化新组累加数组
count = 1
else:
# 同组后续行:逐列累加
for i in range(len(nums)):
cols[i] += nums[i]
count += 1
# 文件结束,输出最后一组
dump(prev, cols, count)关键设计说明:
- ✅ 组识别机制:严格以 _1 作为组起始信号(如 book_1、cook_1),确保逻辑清晰、无歧义;
- ✅ 内存友好:不加载全部数据到内存,适合大文件流式处理;
- ✅ 类型安全:使用 float() 转换,兼容整数与小数输入;
- ⚠️ 注意事项:
- 输入文件需保证每行至少含 2 列(键 + 一个数值),否则 rsplit("_", 1) 或 map(float, values) 可能报错,建议增加异常处理(如 try/except ValueError);
- 若存在 xxx_0 或非数字后缀(如 xxx_a),需扩展 suffix == "1" 的判断逻辑;
- 输出为标准浮点格式(如 2.0),如需控制小数位数,可在 print 中使用格式化:f"{v:.1f}"。
运行后,输入示例将精准输出:
apple 2.0 3.0 4.0 book 1.0 4.0 5.0 cook 3.0 5.0 6.0 book 2.0 3.0 4.0
该方案兼顾可读性、健壮性与低依赖性,是处理此类“隐式分组+行间聚合”任务的典型 Python 实践。









