如何筛选Python列表中各文件夹下路径最短的文件对象
筛选每个文件夹分支下路径最短的文件
我有如下数据:
import datetime data = [{'name': 'root/folder1/f1/s1.csv' , 'last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name': 'root/folder2/f2/s2/file.csv', 'last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name': 'root/folder2/f_1/f_2/f_3/file.csv', 'last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name': 'root/folder2/f_1/f_2/f_3/f_4/f_5/file.csv','last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name': 'root/folder2/f3/s3/file.csv', 'last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name': 'root/folder3/f3/s3/s4/file4.csv','last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)}, {'name' : 'root/folder3/f3/s3/s4/s5/s6/file4.csv','last_modified': datetime.datetime(2022, 8, 4, 18, 43, 13)} ]
我需要筛选出每个文件夹分支下路径最短的文件,规则如下:
folder1中仅有一个文件,直接保留folder2中,root/folder2/f_1/f_2/f_3/file.csv和root/folder2/f_1/f_2/f_3/f_4/f_5/file.csv属于同分支路径,保留路径更短的前者;root/folder2/f3/s3/file.csv是独立路径,直接保留folder3同理保留路径最短的root/folder3/f3/s3/s4/file4.csv
预期输出
data = [{'name': 'root/folder1/f1/s1.csv'}, {'name': 'root/folder2/f2/s2/file.csv'}, {'name': 'root/folder2/f_1/f_2/f_3/file.csv'}, {'name': 'root/folder2/f3/s3/file.csv'}, {'name': 'root/folder3/f3/s3/s4/file4.csv'} ]
当前尝试
我试过通过统计路径斜杠数量筛选最短路径,但不知道怎么针对每个子文件夹分支判断,代码如下:
import os data_dict = {} for item in data: dir = os.path.dirname(item['name']) if dir not in data_dict: item['count'] = 1 data_dict[dir] = item else: count = data_dic[dir]['count'] + 1 if item['last_modified'] > data_dict[dir]['last_modified']: data_dict[dir] = item data_dic[dir]['count'] = count result = list(data_dict.values())
解决方案
核心逻辑是优先保留短路径,同时排除所有属于已保留路径子目录的长路径。具体实现步骤:
- 按路径分割后的长度排序,短路径优先处理,确保先保留分支里最短的路径
- 维护已保留路径列表,每次处理新路径时,判断它是否是已保留路径的子目录,或者已保留路径是否是它的子目录,据此决定保留或替换
代码实现:
import os # 按路径长度从小到大排序,短路径先处理 sorted_data = sorted(data, key=lambda x: len(x['name'].split('/'))) kept_paths = [] for item in sorted_data: current_path = item['name'] need_keep = True to_remove = None # 检查当前路径与已保留路径的关系 for idx, kept in enumerate(kept_paths): common_prefix = os.path.commonprefix([current_path, kept]) if common_prefix == kept: # 当前路径是已保留路径的子目录,跳过 need_keep = False break elif common_prefix == current_path: # 已保留路径是当前路径的子目录,需要移除长路径 to_remove = idx break if to_remove is not None: del kept_paths[to_remove] if need_keep: kept_paths.append(current_path) # 转换为预期的输出格式 result = [{'name': path} for path in kept_paths] print(result)
代码说明
- 排序处理:短路径优先进入判断,确保分支里最短的路径先被保留,后续长路径如果属于该分支会直接被排除
- 路径关系判断:用
os.path.commonprefix获取两个路径的公共前缀,以此判断是否存在子目录关系 - 动态维护保留列表:如果发现已保留的路径是当前路径的子目录,就移除长路径,替换为更短的当前路径
运行后即可得到符合要求的筛选结果。
内容的提问来源于stack exchange,提问作者newbiee
相关产品推荐
相关产品推荐

