检测文件名列表是否具有匹配图像文件名的算法?

Algorithm to detect if a file name list has matching image file name?

我有很多文件。有些是 ziprar 文件的存档。其中一些具有名称匹配的图像。 例如:

d:\data\archive1.zip
d:\data\archive1.jpg
d:\data\archive2.rar
d:\data\archive2.png
d:\data\archive3.zip [This one doesn't have an image]

图像扩展名是 pngjpgjpegwebpgif

我需要一种方法来区分那些具有同名图像对的文件和没有这种图像对的文件。 这些文件路径在字符串列表中。我尝试执行以下操作,只获取没有扩展名的路径:

for i in range(len(file_path_list)):
    print(file_path_list[i])
    fname = file_path_list[i].rsplit('.',1)[0]
    tosearch_list = list(file_path_list)
    tosearch_list.pop(i)

    for x in tosearch_list:
        if x.rsplit('.',1)[0] == fname:
            print(f"{x} is a matching file")

然后对于列表中的每个条目,我将不得不搜索列表中没有扩展名的剩余条目以找到匹配项。

archive1 将不得不搜索列表中剩余的条目并找到具有相同名称的其他文件。名称没有任何特定顺序。这是最快的方法还是有更好的方法?

您可以为zip文件和图片文件创建字典,并通过集合操作获取缺失的名称。这是一个例子:

file_path_list=[
    "d:\data\archive1.zip",
    "d:\data\archive1.jpg",
    "d:\data\archive2.rar",
    "d:\data\archive2.png",
    "d:\data\archive3.zip",
    "d:\data\some.bad.filename.zip",
]

zip_dict = {}
img_dict = {}
for path in file_path_list:
    fname, fext = os.path.splitext(path)
    if fext in (".zip", ".rar"):
        zip_dict[fname] = path
    elif fext in (".jpg", ".png"):
        img_dict[fname] = path

zip_no_img_names = set(zip_dict.keys()).difference(set(img_dict.keys()))

soln_files = [zip_dict[k] for k in zip_no_img_names] 
# ['d:\data\archive3.zip', 'd:\data\some.bad.filename.zip']
  1. 截掉一个扩展部分(即.png),最简单的方法是从末尾向后移动到开头,直到看到第一个.字符。
  2. 剪切后,保留 dictset,其中关键是剩余的 string - 一个没有扩展名的文件名,可以有效地跟踪重复。
  3. 如果找到这样的重复,那么你就找到了匹配项。如果您关心可能出现在不同组合中的扩展名和匹配项,您可能希望使用 dict,其中键为 string 并且找到的扩展名的类型值为 list。例如,如果您同时拥有 my_file.pngmy_file.txtmy_dict['my_file'] == {'.png', '.txt'}.

以下是使用 itertools.groupby() function in conjunction with pathlib.Path 实例保存文件路径(使它们更易于处理)的方法。

代码首先将文件路径转换为Paths,然后通过排序对它们进行分组并忽略文件扩展名。接下来,它使用 groupby() 函数将排序后的列表分组为 sub-lists 个共享公共路径的文件。完成后,它会打印出每个组以及其中一个是否为图像文件的指示符。

from itertools import groupby
from pathlib import Path
from pprint import pprint


image_extensions = {'.png', '.jpg', '.jpeg', '.webp', '.gif'}
archive_extensions = {'.zip', '.rar'}
allowed_extensions = image_extensions | archive_extensions

# Raw filepaths in random order.
filepaths = ['d:\data\archive1.zip',
             'd:\data\archive3.zip',
             'd:\data\archive2.rar',
             'd:\data\archive2.png',
             'd:\data\archive1.jpg']

filepaths = [Path(filepath) for filepath in filepaths]  # Convert to pathlib.Paths
filepaths = [filepath for filepath in filepaths if filepath.suffix in allowed_extensions]

def sort_key(filepath):
    return ''.join(filepath.parts[:-1]), filepath.parts[-1]

filepaths.sort(key=sort_key)
#pprint(filepaths)

def keyfunc(filepath):
    return ''.join(filepath.parts[:-1]), filepath.stem

groups = []
for k, g in groupby(filepaths, keyfunc):
    groups.append(list(g))  # Append filepath group.

for group in groups:
    has_image = any((filepath.suffix in image_extensions) for filepath in group)
    print(group, 'Has image' if has_image else 'No image')

示例输出:

[WindowsPath('d:/data/archive1.jpg'), WindowsPath('d:/data/archive1.zip')] Has image
[WindowsPath('d:/data/archive2.png'), WindowsPath('d:/data/archive2.rar')] Has image
[WindowsPath('d:/data/archive3.zip')] No image