如何使用bisect模块在按文件名排序的路径列表中查找指定文件名?
如何使用bisect模块在按文件名排序的路径列表中查找指定文件名?
嘿,我明白你的需求了——你有一堆带完整路径的文件名,已经按纯文件名排好序了,现在想用bisect快速定位某个特定的文件名对吧?但你当前的代码肯定跑不通,因为你犯了一个很容易踩的小坑:排序时用的是文件名作为key,但查找时直接拿纯文件名和完整路径字符串比,规则不匹配,bisect自然找不到正确的位置。
下面给你两种可行的解决办法,你可以根据自己的场景选:
方法一:同步维护文件名列表(简单直观)
这个思路很直接:既然我们是按文件名排序的,那不如在收集路径的时候,同时单独存一份对应的纯文件名列表,排序的时候把两个列表绑定在一起同步排序,之后用bisect在纯文件名列表里找,找到的索引直接对应到路径列表就行。
代码示例:
import os import bisect # 替换成你要遍历的目标目录 target_dir = "./your_target_folder" path_list = [] filename_list = [] # 遍历目录收集路径和对应的文件名 for dp, _, filenames in os.walk(target_dir): for name in filenames: full_path = os.path.join(dp, name) path_list.append(full_path) filename_list.append(name) # 同步按文件名排序两个列表 # 把文件名和路径打包成元组排序,再解包分开 sorted_pairs = sorted(zip(filename_list, path_list), key=lambda item: item[0]) filename_list, path_list = zip(*sorted_pairs) # 如果需要列表类型(元组是只读的),可以转成list: # filename_list, path_list = list(filename_list), list(path_list) # 要查找的目标文件名 target_filename = "C001567.jpg" # 在文件名列表中用bisect查找 index = bisect.bisect_left(filename_list, target_filename) # 验证是否找到 if index != len(filename_list) and filename_list[index] == target_filename: print(f"找到目标路径:{path_list[index]}") else: print(f"未找到文件名 {target_filename}")
方法二:实现支持key参数的bisect查找函数
如果不想维护额外的文件名列表,我们可以自己写一个支持key的bisect_left函数,让查找时用和排序时完全一样的规则(提取文件名)来比较,这样就不用额外存列表了。
代码示例:
import os import bisect # 自定义支持key的bisect_left函数 def bisect_left_with_key(a, x, key): lo = 0 hi = len(a) while lo < hi: mid = (lo + hi) // 2 # 用key函数提取当前元素的对比值,和目标x比较 if key(a[mid]) < x: lo = mid + 1 else: hi = mid return lo # 遍历目录收集路径 target_dir = "./your_target_folder" path_list = [] for dp, _, filenames in os.walk(target_dir): for name in filenames: path_list.append(os.path.join(dp, name)) # 按文件名排序路径列表(和你原来的代码一致) path_list.sort(key=lambda p: os.path.basename(p)) # 要查找的目标文件名 target_filename = "C001567.jpg" # 用自定义的bisect函数查找,key和排序时保持一致 index = bisect_left_with_key(path_list, target_filename, key=lambda p: os.path.basename(p)) # 验证是否找到 if index != len(path_list) and os.path.basename(path_list[index]) == target_filename: print(f"找到目标路径:{path_list[index]}") else: print(f"未找到文件名 {target_filename}")
最后再给你理清楚核心问题:你原来的代码无法工作,是因为排序时用os.path.basename(p)把完整路径转换成纯文件名来排序,但bisect默认是直接比较列表元素(完整路径字符串)和你传入的f(纯文件名字符串)。比如完整路径"/home/user/C001567.jpg"和"C001567.jpg"做字符串比较时,因为/的ASCII码比C小,所以完整路径会被认为比纯文件名“小”,bisect会返回错误的索引,自然找不到匹配项。
所以记住这个核心原则:排序用的key和查找用的比较规则必须完全一致,这样bisect才能发挥它的快速查找作用。
内容来源于stack exchange
相关产品推荐
相关产品推荐

