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