基于文件名加速文件匹配

2024-10-03 15:26:05 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我有两个目录,有两种不同的文件类型(例如.csv,.png),但基本名称相同(例如1001\u 12\u 15.csv,1001\u 12\u 15.png)。我在每个目录中有数千个文件。你知道吗

我想做的是得到文件的完整路径,在匹配了基名之后,然后对两个文件的整个路径做些什么。你知道吗

我想请你帮我加速手术。你知道吗

我的方法是:

csvList=[a list with the full path of each .csv file]
pngList=[a list with the full path of each .png file]



for i in range(0,len(csvlist)):
    csv_base = os.path.basename(csvList[i])
    #eg 1001
    csv_id = os.path.splitext(fits_base)[0].split("_")[0]

    for j in range(0, len(pngList)):
        png_base = os.path.basename(pngList[j])
        png_id = os.path.splitext(png_base)[0].split("_")[0]
        if float(png_id) == float(csv_id):
            DO SOMETHING

我又试过了,比如:

for csv_file in csvList:
    try:
        csv_base = os.path.basename(csv_file)

        csv_id = os.path.splitext(csv_base)[0].split("_")[0]

        rel_path = "/path/to/file"
        pattern = "*" + csv_id + "*.png"

        reg_match = fnmatch.filter(pngList, pattern)
        reg_match=" ".join(str(x) for x in reg_match)
        if reg_match:
            DO something

似乎使用嵌套for循环更快。但我希望它能更快。有没有其他方法可以加速我的代码?你知道吗


Tags: 文件csvpathinidforbasepng
2条回答

您可以在O(n)中建立一个搜索索引,然后在每个O(1)中查找其中的项。如果您的问题是完全匹配的,那么平面查找dict就足够了:

from os.path import basename, splitext

png_lookup = {
    splitext(basename(png_path))[0] : png_path
    for png_path in pngList
}

这允许您直接查找每个csv文件对应的png文件:

for csv_file in csvList:
    csv_id = splitext(basename(csv_file)[0]
    try:
        png_file = png_lookup[csv_id]
    except KeyError:
        pass
    else:
        # do something

最后,您将有一个O(n)查找构造和一个单独的O(n)迭代,其中包含一个嵌套的O(1)查找。总的复杂度是O(n)与初始的O(n^2)相比。你知道吗

首先,像这样优化现有循环的语法

for csv in csvlist:
    csv_base = os.path.basename(csv)
    csv_id = os.path.splitext(csv_base)[0].split("_")[0]

    for png in pnglist:
        png_base = os.path.basename(png)
        png_id = os.path.splitext(png_base)[0].split("_")[0]
        if float(png_id) == float(csv_id):
            #do something here

嵌套循环非常慢,因为需要运行png循环n2次

然后,您可以使用列表理解数组索引来加快速度

## create lists of processed values 
## so you dont have to keep running the os library
sv_base_list=[os.path.basename(csv) for csv in csvlist]
csv_id_list=[os.path.splitext(csv_base)[0].split("_")[0] for csv_base in csv_base_list]
png_base_list=[os.path.basename(png) for png in pnglist]
png_id_list=[os.path.splitext(png_base)[0].split("_")[0] for png_base in png_base_list]


## run a single loop with list.index to find matching pair and record base values array

csv_png_base=[(csv_base_list[csv_id_list.index(png_id)], png_base)\
                   for png_id,png_base in zip(png_id_list,png_base_list)\
                   if png_id in csv_id_list]

## csv_png_base contains a tuple contianing (csv_base,png_base)
  • 这种使用列表索引的逻辑大大减少了循环计数,并且没有重复的os-lib调用
  • 列表理解比正常循环稍微快一点

您可以在列表中循环并对这些值进行处理 例如

for csv_base,png_base in csv_png_base:
    #do something

熊猫将更快地完成这项工作,因为它将使用C库运行循环

相关问题 更多 >