如何对TXT文件基于双重条件排序:按title_topic聚合并按post_number自然数字排序
大JSON行文本的分组与自然排序实现方案
核心实现逻辑
完全匹配两个排序需求,无冗余处理:
- 第一级排序:按
title_topic字段值聚合分组,相同取值的条目归为同一组 - 第二级排序:每组内部按
post_number的实际数字值做自然排序,规避字符串字典序导致的错序问题
具体操作步骤
1. 定制排序解析规则
针对post_number的特殊取值写专门的解析逻辑,从根源上避免排序错误:
- 取值为
"null"的条目,可灵活调整排序优先级(比如放在组的最前/最后位置) - 带尾随小数点的数字字符串(如
"1."、"10."),去掉小数点后转为整数作为排序值,实现1→2→…→9→10→11的正确自然顺序 title_foreach_post字段无需参与排序逻辑,无论取值是和title_topic一致还是空数组,都不影响分组和排序结果
2. 逐行读取适配大文件
逐行解析大TXT内容,将条目按title_topic存入字典结构,无需一次性把全量文件加载到内存,避免大文件内存溢出:
import json from collections import import defaultdict # 存储结构:key为title_topic值,value为对应条目的(排序键, 原始条目)列表 topic_groups = defaultdict(list) def parse_post_number(post_num_str): # null值的排序优先级:返回-1时排在组最前,返回极大值时排在组最后 if post_num_str == "null": return -1 # 去掉尾随小数点,提取纯数字转为整数作为排序值 pure_num = post_num_str.rstrip('.') return int(pure_num) with open("input_large.txt", "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue entry = json.loads(line) topic = entry["title_topic"] post_sort_key = parse_post_number(entry["post_number"]) topic_groups[topic].append( (post_sort_key, entry) )
3. 两层排序写出结果
先对所有topic分组按规则排序(默认按topic名称字典序,可自定义调整组的排列顺序),再对组内条目按解析后的数字键排序,逐行写入输出文件,全程不修改原始JSON字段内容:
with open("output_sorted.txt", "w", encoding="utf-8") as f: # 对所有topic分组排序,需要自定义组顺序时替换sorted的key参数即可 for topic in sorted(topic_groups.keys()): group_content = topic_groups[topic] # 组内按post_number的解析值做自然排序 group_content.sort(key=lambda x: x[0]) # 写出原始条目,不改动原有结构 for _, entry in group_content: f.write(f"{json.dumps(entry, ensure_ascii=False)}\n")
常见避坑点
- 不要直接对
post_number做字符串字典序排序,否则会出现"1." < "10." < "2."的错序结果,完全不符合自然排序要求 - 1900个topic的规模下,当前实现的内存占用极低,哪怕单行JSON体积稍大也不会出现内存溢出问题
- 如果遇到体积特别大的文件,可调整逻辑为逐组排序后实时写出,进一步降低内存占用
内容的提问来源于stack exchange,提问作者Artemis
相关产品推荐
相关产品推荐

