
本文讲解如何正确处理按行分割的管道分隔文件列表,对每行独立去扩展名后统计原始文件名出现频次,仅保留频次为 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免费学习笔记(深入)”;
foo.mp3|bar.txt|baz.mp3 thud.mp3
注意事项:
- 文件名严格为“纯字母数字 + 单个点 + 扩展名”,因此 split('.')[0] 安全可靠,无需正则;
- 每行独立处理,无状态依赖,适合流式读取大文件(可改用 for line in open(...) 迭代);
- 若某行所有基础名都重复(如第二行全为 wub),则输出为空行(符合题目逻辑);
- 保持原始顺序:我们遍历 filenames 列表而非 Counter 的键,确保输出顺序与输入一致。
该方案时间复杂度为 O(n),空间复杂度为 O(m)(m 为单行文件数),完全满足题目约束(≤500 行,≤100 字符/行)。










