迭代字典键引用的未知数量的列表,以便比较每个列表中的值

时间:2011-12-16 16:34:08

标签: python list loops dictionary

我最近开始编写一个小脚本,其中我的目的是输入一个完整的文件目录(本例中为电子书,epub,mobi,djvu,pdf),找到彼此匹配的文件(几乎)除了扩展名之外的所有方式(例如同一个“书”的多个电子书文件格式,为该“书”创建一个目录,并将文件放在目录中,以便于导入Calibre。

我决定使用列表字典文件的数据结构,其中文件名按扩展名(键)分组到列表(值)中。如果不清楚,这是我的结构模型:{fileExtension:[fileName,fileName,...],fileExtension:[fileName,fileName,...] ...}

我遇到的问题是为了匹配每个列表中的各个值,按键分组我不能只使用for循环嵌套如果我不一定知道我有多少个键会有。

在Windows 64位环境下用Python 2.7.2编写

代码:

import glob

workDirectory = 'E:\Some eBooks'
fileExtensions  = ['mobi','epub','pdf','djvu']

# Create an appropriate holding structure for our results {fileExtension:[fileName,fileName,...]}
foundFiles = dict.fromkeys(fileExtensions,[])

for ext in fileExtensions:
    print('Looking for ' + ext + ' files in ' + workDirectory)
    for file in glob.glob(workDirectory + '/*.' + ext):
        foundFiles[ext].append(file)

我知道我可以静态地编写针对文件内容的循环操作'知道将会有fileExtensions创建的四个密钥,但是一旦工作正常,我希望代码采用任意数字通过argparse将值fileExtensions

我想我的核心问题是,如何使用可变数量的字典键作为同一迭代中列表的引用来循环多个列表?如果我知道每个列表的静态名称,并且每个列表都有相同数量的值,我会这样做:

for one, two, three, four in list1 list2 list3 list4:
    ......

但我知道这样做不会起作用,因为我不会立即知道我将循环的列表数量,并且我知道每个列表所需的迭代次数不匹配。

我有一种沉闷的感觉,我正在过度思考这个问题,以至于让自己感到困惑。也许一组嵌套列表可以工作,但出于某种原因,我认为我可以更直接的方式做到这一点。

有关如何继续的任何建议将不胜感激。

3 个答案:

答案 0 :(得分:2)

相反,我会按照名称存储找到的文件,以便在您阅读它们时对它们进行分组。像这样:

foundFiles = {}
for ext in fileExtensions:
    print('Looking for ' + ext + ' files in ' + workDirectory)
    for file in glob.glob(workDirectory + '/*.' + ext):
        basename = os.path.basename(os.path.splitext(file)[0])
        grouped_files = foundFiles.get(basename, [])
        grouped_files.append(file)
        foundFiles[basename] = grouped_files

现在你有foundFiles,其中键是文件的基本名称,值是文件的路径。例如:

{ 'batman': ['/some/path/batman.pdf', '/other/path/batman.mobi']
  'superman': ['/some/path/superman.epub', '/other/path/superman.djvu'] }

答案 1 :(得分:1)

遍历workDirectory目录树并收集fileExtensions个扩展名的所有文件:

import os
from collections import defaultdict

fileExtensions  = ('.mobi', '.epub', '.pdf', '.djvu')

foundFiles = defaultdict(list)
for dirpath, dirs, files in os.walk(workDirectory):
    for file in files:
        if file.endswith(fileExtensions):
           basename = os.path.splitext(file)[0]
           foundFiles[basename].append(os.path.join(dirpath, file))

foundFiles的格式与@jterrace's answer中的格式相同:

{
    "batman": [
        "/some/path/batman.pdf", 
        "/other/path/batman.mobi"
    ], 
    "superman": [
        "/some/path/superman.epub", 
        "/other/path/superman.djvu"
    ]
}

答案 2 :(得分:0)

为什么你不使用包含所有目录中所有文件的简单列表,并使用正则表达式,你可以迭代和列表,找到与当前元素匹配相同文件名的所有文件?