
本文详解如何正确处理多行管道分隔的文件名,逐行统计去除扩展名后的出现频次,仅保留出现恰好一次的原始文件名(含扩展名),并以相同格式输出。
在该挑战中,核心逻辑并非简单去重(set 去重会丢失频次信息),而是识别每行中“基础名(不含扩展名)出现次数为 1”的原始文件名。例如 wub.mp3|wub.txt|wub.png 去掉扩展名后均为 wub,出现 3 次 → 全部排除;而 quux.mp3|quux.txt|thud.mp3 中 quux 出现 2 次(排除两者),thud 出现 1 次(保留 thud.mp3)。
正确解法需两步:
- 按行分割,再按 | 拆分每行的文件名;
- 对每行内所有文件名执行:
✅ 提取基础名(filename.split('.')[0]);
✅ 统计各基础名的出现频次(推荐使用 collections.Counter);
✅ 筛选出频次为 1 的原始文件名;
✅ 按原顺序(非去重顺序!)拼接结果(注意:题目未要求保持输入顺序?但示例输出隐含保留原始位置顺序,故应遍历原列表筛选,而非依赖 Counter.keys())。
以下是健壮、可读性强的 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('|')
# 提取所有基础名(不含扩展名)
stems = [f.split('.')[0] for f in filenames]
# 统计频次
stem_count = Counter(stems)
# 筛选:仅保留 stem 出现次数为 1 的原始 filename(保持原始顺序)
unique_files = [f for f in filenames if stem_count[f.split('.')[0]] == 1]
result.append('|'.join(unique_files))
return '\n'.join(result)
# 测试验证
test_input = "foo.mp3|bar.txt|baz.mp3\nwub.mp3|wub.mp3|wub.mp3|wub.txt|wub.png\nquux.mp3|quux.txt|thud.mp3"
print(find_unique_filenames(test_input))输出:
立即学习“Python免费学习笔记(深入)”;
foo.mp3|bar.txt|baz.mp3 thud.mp3
✅ 关键点说明:
- 使用 Counter(stems) 高效统计频次,避免手动字典计数;
- 筛选时遍历原始 filenames 列表,确保输出顺序与输入一致(如 foo.mp3|bar.txt|baz.mp3 三者基础名均唯一,全部保留且顺序不变);
- 不依赖 set 或 dict.keys(),避免无序或丢失重复项判断逻辑;
- 显式处理空行,增强鲁棒性;
- 每行独立处理,完全符合题目“no logic carries forward”要求。
⚠️ 注意事项:
- 文件名严格为“纯字母数字 + 单个点 + 扩展名”,因此 split('.')[0] 安全可靠(无需正则或 os.path.splitext);
- 若某行无任何唯一文件名(如全为 a.txt|a.log|b.json|b.xml),对应输出为空字符串(即该行留空),符合逻辑;
- 行长度 ≤100 字符、总行数 ≤500,本实现时间复杂度为 O(N×M),完全满足性能要求。
掌握频次统计与条件筛选的组合,是处理此类“基于重复性过滤”问题的核心能力。










