合并两个部分包含的文件及其属性列表的最有效方法

时间:2016-08-19 00:10:09

标签: python performance list dictionary

我有一个运行自定义cli的系统,其中包含lsdir命令的变体,返回工作目录中的文件和文件夹列表。

问题是,我可以运行带有标志的命令,该标志返回文件及其时间戳(创建日期和上次修改日期),或者返回文件及其文件大小的标记。没有办法在单个cli命令中同时使用它们。

在获取带时间戳的列表时会出现进一步的复杂情况,只返回部分文件(所有以某些前缀结尾的文件都被省略)。这两个列表都没有任何特定的顺序。

我希望在一个地方创建一个包含每个文件的所有信息的字典。什么是最干净,最有效,最pythonic的方法呢?

快速数据样本:

dir -time列出了506个元素。只有(但不是全部)以.ts结尾的文件都有时间戳。某些文件显示在列表中但没有时间戳,某些文件(例如以.index结尾的任何内容)根本不会显示在列表中。

ch20prefix_20_182.ts    2014-10-22 16:06:20 - 2014-10-22 16:08:51                                                                    
ch21prefix_21_40.ts     2014-10-14 16:15:42 - 2014-10-14 16:16:51                                                       
modinfo_sdk1.23b24L                                                                                                     
bs780_ntplatency                                                                                                        
ch10prefix_10_237.ts    2014-10-27 11:05:10 - 2014-10-27 11:07:33                                                       
ch10prefix_10_277.ts    2014-10-30 14:03:51 - 2014-10-30 14:04:24                                                                                                                                                                    
video1_6_1.ts                                                                                                           
ch11prefix_11_179.ts    2014-10-22 14:53:50 - 2014-10-22 14:56:00`

dir -size给出了967个元素的列表。这里存在所有文件,所有文件都有文件大小。

ch10prefix_10_340.index 159544
ch2prefix_2_705.ts      75958204
<ts220> 0
ch11prefix_11_148.ts    19877616
ch10prefix_10_310.ts    7373924
ch11prefix_11_111.index 17112
ch11prefix_11_278.index 1368
ch2prefix_2_307.ts      6492580
channelConfig.xml.2HD   18144
ch21prefix_21_220.ts    12893604
ch20prefix_20_128.index 1720

有一些押韵和理由,这就是为什么有些文件出现而其他文件没出现的原因,为什么有些文件有时间戳,有些则没有,但这与这个问题无关。

我对如何处理它的看法:

我想要的最终输出是一个字典,每个键都作为文件名,它的值是另一个带有键/值对的字典,用于Time Created,Time Mod,fileSize。通过这种方式,您可以轻松查找每个文件的所有3条信息。

然而,对我来说,困难的部分是找到一种有效的方法来组合每个列表中的数据。首先想到的是循环遍历较大的列表(文件大小),然后对于每个元素,检查它是否在较小的列表中,如果它是(并且有时间戳),则添加数据。但这非常低效。虽然我提前知道的较大列表中的某些文件在其他列表中没有时间戳,但我不能说对于没有时间戳的所有文件。

这些列表是未排序的,但是如果按照文件名对它们进行排序,则会发生这种情况,这样可以更快地从另一个列表中查找每个文件,但考虑到对列表进行排序的运行时,它仍然可能不值得努力。

那么,这里最有效的方法是什么?我主要关心的是运行时和可读性,但欢迎将其他因素包含在我如何处理这个问题中。

2 个答案:

答案 0 :(得分:1)

很难从你的问题中看出你想要的结果是什么。如果您想要两个列表中的所有文件,即使它们只出现在一个或另一个文件中,只需通过两个文件并使用collections.defaultdict创建字典

from collections import defaultdict
d = defaultdict(dict)
with open('fileA.txt') as f:
    for line in f:
        name, time = line[:24], line[24:]
        name, time = name.strip(), time.strip()
        time_created, time_modified = time.split(' - ')
        d[name]['time_created'] = time_created
        d[name]['time_modified'] = time_modified

with open('fileB.txt') as f:
    for line in f:
        name, size = line[:24], line[24:]
        name, size = name.strip(), size.strip()
        d[name]['size'] = size

如果您的最终结果只包含出现在两个列表中的文件,那么请在构建单独词典的每个列表上进行一次传递。

dA = defaultdict(dict)
dB = defaultdict(dict)

with open('fileA.txt') as f:
    for line in f:
        name, time = line[:24], line[24:]
        name, time = name.strip(), time.strip()
        try:
            time_created, time_modified = time.split(' - ')
        except ValueError:
            time_created, time_modified = '', ''
        dA[name]['time_created'] = time_created
        dA[name]['time_modified'] = time_modified

with open('fileB.txt') as f:
    for line in f:
        name, size = line[:24], line[24:]
        name, size = name.strip(), size.strip()
        dB[name]['size'] = size

然后对其中一个词典进行传递,创建具有公共键的第三个词典。

d = defaultdict(dict)
for k, v in dA.items():
    if k in dB:
        d[k] = v
        d[k].update(dB[k])

因为这是解决方案的唯一答案(到目前为止)并且@Brian C没有提供解决方案,所以这必须是最有效的。

答案 1 :(得分:0)

听起来像是Sqlite的一个很好的用例。 Python有good support。您可以通过传递正确的参数来使用基于内存的纯数据库,而不是创建基于磁盘文件的数据库。首先,我创建了2个表 - tblFileNTimeStamp(文件名(PK),时间戳)和tblFileNSize(文件名(PK),filesize)。使用这两个命令的输出来填充数据库,并使用主键上的连接来选择所需的结果。