2

所以我有 2 个具有 2 种不同文件类型(例如 .csv、.png)但具有相同基本名称(例如 1001_12_15.csv、1001_12_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

此外,我尝试了 fnmatch 类似的东西:

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 循环更快。但我希望它更快。还有其他方法可以加快我的代码吗?

4

2 回答 2

1

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

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

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

于 2019-07-21T12:13:19.727 回答
0

您可以在 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(1) 查找的单独 O(n) 迭代。与最初的 O(n^2) 相比,总复杂度为 O(n)。

于 2019-07-21T12:58:14.107 回答