基于名称列表过滤路径列表:求更简洁优雅的实现方法
问题:过滤路径列表,排除包含指定名称的项
我手里有两个列表:names存着要排除的名称,paths是一堆待过滤的路径,想生成一个新列表,只留下不包含names里任何名称的路径。
给个示例数据:
names = ['name_1', 'name_2', 'name_3', 'name_4', 'name_5'] paths = ['dataset/name_1/00000003.jpg', 'dataset/name_2/00000001.jpg', 'dataset/name_3/00000000.png', 'dataset/name_4/00000002.jpg', 'dataset/name_5/00000000.jpg', 'dataset/name_6/00000002.jpg']
预期结果是:
['dataset/name_6/00000002.jpg']
我现在的写法有点啰嗦,代码是这样的:
check = [] for path in paths: exist_boolean = any([path.__contains__(x) for x in names]) check.append(exist_boolean) check_final = [not i for i in check] list(compress(paths, check_final))
想问问有没有更简洁优雅的实现方式?
优雅的实现方案
1. 一行列表推导式搞定核心逻辑
最直观的优化就是把整个判断逻辑浓缩到一行列表推导式里,省去那些中间变量,代码清爽多了:
names = ['name_1', 'name_2', 'name_3', 'name_4', 'name_5'] paths = ['dataset/name_1/00000003.jpg', 'dataset/name_2/00000001.jpg', 'dataset/name_3/00000000.png', 'dataset/name_4/00000002.jpg', 'dataset/name_5/00000000.jpg', 'dataset/name_6/00000002.jpg'] result = [path for path in paths if not any(name in path for name in names)]
逻辑很清晰:遍历每个路径,只保留那些没有任何一个name出现在路径里的项,可读性拉满,还省了一堆冗余代码。
2. 精准匹配目录名,避免误判
如果担心name in path会翻车(比如某个文件名刚好带name_1的字符串,但不是我们要排除的目录),可以用os.path模块来精准提取路径里的目录部分:
import os # 把names转成集合,查找速度更快,尤其是列表大的时候 names_set = set(names) result = [ path for path in paths # 处理路径兼容不同系统,分割后取dataset后面的目录名 if os.path.normpath(path).split(os.sep)[1] not in names_set ]
这里转集合是因为集合的in操作是O(1),比列表的O(n)高效很多,大数据量下优势明显。
3. 用生成器表达式省内存
要是你的paths列表特别大,不想一次性生成整个结果占内存,可以用生成器表达式代替列表推导式,迭代的时候才逐个生成元素:
result_gen = (path for path in paths if not any(name in path for name in names))
之后直接遍历result_gen就行,需要转列表的话再用list(result_gen)。
内容的提问来源于stack exchange,提问作者 owise
相关产品推荐
相关产品推荐

