假设我们有100k目录和1M文件,其结构存储在这样的列表中:
DIRS = ['C:\\', 'C:\\LAB\\', 'C:\\ABB\\', 'C:\\CDA\\', 'C:\\EABZ\\', 'C:\\CDA\\FOO\\']
FILES = [['a.txt', 2], ['b.txt', 3], ['c.txt', 3], ['r.txt', 1],
['s.txt', 1], ['k.txt', 0], ['m.txt', 4]] # [filename, dir_index], for
# example, a.txt is here: C:\ABB\a.txt
现在,我想搜索其目录名称包含AB
的文件。我在这里看到的唯一方法如下。
(1)首先获取包含DIRS
的{{1}}索引:
AB
我们只在I = [i for i in range(len(DIRS)) if 'AB' in DIRS[i]] # here [1, 2, 4]
# but can be of size 1000
上循环一次,即100k,这没关系。
(2)现在我们需要循环DIRS
(例如可以是1000)和I
(100万),这太多了因为1000 * 1M = 10亿次操作:
FILES
这是太多的操作! 如何在保持FOUND_FILES = []
for i in I:
for f in FILES:
if f[1] == i:
FOUND_FILES.append(f)
/ DIRS
数据结构的同时进行更有效的研究?(如果100%完全不可能,我应该考虑哪种其他结构?)
注意:(2)的替代方案并没有加速我的想法:
FILES
答案 0 :(得分:1)
如果你做{{1>,替代方法的时间复杂度可以减少到 O (n)(其中 n 是FILES
的长度)一个集合,而不是原始的 O (n * m)(其中 m 是I
的长度):
I
集合的一个重要用途是快速成员资格查找; 0 (1)。
通过使用列表推导来构建最终的I = {i for i, x in enumerate(DIRS) if 'AB' in x}
列表,您还可以获得一些重要的CPU时间:
FOUND_FILES
如果您通过阅读父目录的整个内容来构建文件列表,请使用FOUND_FILES = [f for f in FILES if f[1] in I]
,而应该应用glob.glob
来直接从您的模式构建列表。< / p>
答案 1 :(得分:0)
DIRS = ['C:\\', 'C:\\LAB\\', 'C:\\ABB\\', 'C:\\CDA\\', 'C:\\EABZ\\', 'C:\\CDA\\FOO\\']
FILES = [['a.txt', 2], ['b.txt', 3], ['c.txt', 3], ['r.txt', 1], ['s.txt', 1], ['k.txt', 0], ['m.txt', 4]]
FOUND_FILES = []
for check_file in FILES:
try:
if 'AB' in DIRS[check_file[1]]:
FOUND_FILES.append(check_file)
except (IndexError, TypeError):
pass
像这样?