
本文介绍一种时间复杂度为 o(n + m) 的高效方案,利用哈希查找替代嵌套遍历,实现将第二组文本文件内容按文件名精准追加到第一组对应文件末尾,避免暴力双重循环,兼顾可读性与工程实用性。
在处理大量有序命名的文本文件(如 aaa.txt, aab.txt, …, zzz.txt)时,若需将另一组离散命名文件(如 ant.txt, cat.txt, lion.txt)的内容按文件名匹配后追加到第一组对应文件中,最直观的双重循环(O(n×m))方案在文件量增大时会显著低效——这正如人类不会从 aaa.txt 开始线性查找 cat.txt,而会直接定位到 ca* 区间。
真正的优化关键在于:放弃“在目标目录中逐个比对”,转为“以目标文件名为键构建查找索引”。python 中可借助 os.listdir() 获取源目录(第二组)所有文件名,再通过集合或字典快速判断其是否存在于目标目录(第一组)中。由于 os.path.isfile() 检查和文件 I/O 是主要开销,而哈希查找平均为 O(1),整体复杂度降至 O(n + m),其中 n、m 分别为两组文件数量。
以下是生产就绪的优化实现:
import os def merge_files_by_name(target_dir: str, source_dir: str, create_missing: bool = False) -> None: """ 将 source_dir 中每个 .txt 文件内容追加到 target_dir 中同名文件末尾。 Args: target_dir: 目标目录(第一组文件所在路径) source_dir: 源目录(第二组文件所在路径) create_missing: 若为 True,当 target_dir 中无对应文件时,自动创建空文件并追加;否则跳过。 """ # 预扫描目标目录,构建存在性集合(仅文件名),O(n) target_files = { f for f in os.listdir(target_dir) if os.path.isfile(os.path.join(target_dir, f)) } # 遍历源目录,单次扫描完成匹配与追加,O(m) for filename in os.listdir(source_dir): source_path = os.path.join(source_dir, filename) if not os.path.isfile(source_path): continue if filename in target_files: target_path = os.path.join(target_dir, filename) try: with open(source_path, 'r', encoding='utf-8') as src_f, open(target_path, 'a', encoding='utf-8') as tgt_f: tgt_f.write('n') # 可选:添加换行分隔 tgt_f.writelines(src_f) except (IOError, UnicodeDecodeError) as e: print(f"警告:无法处理 {filename} — {e}") elif create_missing: # 创建缺失的目标文件并写入内容(非追加,而是首次写入) target_path = os.path.join(target_dir, filename) try: with open(source_path, 'r', encoding='utf-8') as src_f, open(target_path, 'w', encoding='utf-8') as tgt_f: tgt_f.writelines(src_f) print(f"已创建新文件:{target_path}") except Exception as e: print(f"警告:无法创建 {filename} — {e}") # 使用示例 if __name__ == "__main__": merge_files_by_name( target_dir="./first_group", source_dir="./second_group", create_missing=False # 默认跳过不存在的文件 )
✅ 关键优化点说明:
- 零嵌套循环:通过 set 实现 O(1) 成员检查,彻底消除内层遍历;
- 一次预扫描 + 一次主扫描:I/O 和系统调用次数最小化;
- 健壮性增强:支持编码指定(推荐 utf-8)、异常捕获、可选换行分隔;
- 语义清晰控制:create_missing 参数显式区分“严格追加”与“补全创建”逻辑。
⚠️ 注意事项:
- 确保两目录下文件均为纯 .txt(脚本未做扩展名过滤,如需可添加 if filename.endswith(‘.txt’));
- 追加操作是原子性写入,但不保证跨进程安全;高并发场景建议加文件锁;
- 若文件极大(GB 级),应改用流式逐行读写(for line in src_f:)避免内存溢出;
- linux/macOS 下注意路径权限;windows 用户需确保路径中无非法字符。
该方案不仅高效,而且结构清晰、易于测试与维护,是处理此类“键驱动文件合并”任务的标准实践。