跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何用 Python 精确提取每行中“扩展名去除后唯一出现”的文件名

本文讲解如何正确处理按行分割的管道分隔文件列表,对每行独立去扩展名后统计原始文件名出现频次,仅保留频次为 1 的原始完整文件名(含扩展名),并用管道符重新拼接输出。 要解决该问题,关键在于理解题意中的“unique per row, ignoring the file extensions”——它 不是指去重(distinct) ,而是指: 在去除扩展名后,若某个基础名(如 wub、quux)在整个当前行中只出现一次,则保留其原始带扩展名的完整形式;若出现两次及以上,则整行中所有该基础名的文件均被剔除 。 原代码错误地使用了 set,导致只记录了去重后的基础名,完全丢失了频次信息和原始文件名映射关系。正确做法是: 按行处理; 将每行按 | 分割为文件名列表; 对每个文件名提取基础名(filename.split('.')[0]); 使用 collections.Counter 统计每行中各基础名的出现次数; 遍历原始文件名列表,仅保留那些对应基础名计数为 1 的完整文件名; 将筛选后的文件名用 | 拼接成新行。 以下是修正后的完整 Python 实现:
from collections import Counter def find_unique_filenames(text): result = [] for line in text.strip().split('\n'): if not line.strip(): # 跳过空行 continue filenames = line.strip().split('|') # 提取每文件的基础名(不含扩展名) basenames = [f.split('.')[0] for f in filenames] # 统计基础名频次 basename_counts = Counter(basenames) # 仅保留基础名出现恰好 1 次的原始文件名 unique_files = [ fname for fname in filenames if basename_counts[fname.split('.')[0]] == 1 ] result.append('|'.join(unique_files)) return '\n'.join(result) # 测试示例 test_input = """foo.mp3|bar.txt|baz.mp3 wub.mp3|wub.mp3|wub.mp3|wub.txt|wub.png quux.mp3|quux.txt|thud.mp3""" print(find_unique_filenames(test_input))
✅ 输出结果: Python 3.14.3 微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。 下载 立即学习 “ Python免费学习笔记(深入) ”;
foo.mp3|bar.txt|baz.mp3 thud.mp3
注意事项: 文件名严格为“纯字母数字 + 单个点 + 扩展名”,因此 split('.')[0] 安全可靠,无需正则; 每行独立处理,无状态依赖,适合流式读取大文件(可改用 for line in open(...) 迭代); 若某行所有基础名都重复(如第二行全为 wub),则输出为空行(符合题目逻辑); 保持原始顺序:我们遍历 filenames 列表而非 Counter 的键,确保输出顺序与输入一致。 该方案时间复杂度为 O(n),空间复杂度为 O(m)(m 为单行文件数),完全满足题目约束(≤500 行,≤100 字符/行)。

相关文章