Python 搜索dirname具有特定模式的文件
假设我们有100k个目录和1M个文件,其结构存储在如下列表中:Python 搜索dirname具有特定模式的文件,python,list,loops,optimization,filesystems,Python,List,Loops,Optimization,Filesystems,假设我们有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,
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) 首先获取包含
的AB
索引:DIRS
我们只在I = [i for i in range(len(DIRS)) if 'AB' in DIRS[i]] # here [1, 2, 4] # but can be of size 1000
上循环一次,即100k,这没问题DIRS
- (2) 现在我们需要在
(例如可以是1000个)和I
(100万个)上循环,这太多了,因为1000*1M=10亿次操作:文件
FOUND_FILES = [] for i in I: for f in FILES: if f[1] == i: FOUND_FILES.append(f)
注意:我认为(2)的这个替代方案并没有加快任何速度:
如果将
I
设置为一个集合,则替代方法的时间复杂度可以降低到O(n)(其中n是I
的长度),而不是原始的O(n*m)(其中m是I
的长度):
快速成员查找是集的重要用途之一;O(1)
通过使用列表理解来构建最终的FOUND\u文件
list,您还可以获得一些重要的CPU时间:
FOUND_FILES = [f for f in FILES if f[1] in I]
如果您是通过读取父目录的全部内容来构建文件列表的,那么您应该使用say
os.listdir
,直接从您的模式构建一个列表
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
像这样?
集合的一个重要用途是快速成员查找;O(1)
这怎么可能?集合越大,成员查找越慢,不是吗?所以“设置大小”和“成员查找时间”之间应该是成比例的,你不这么认为吗?@Basj-Nope,理想情况下。集合使用哈希表,因此它们不需要按顺序迭代项。足够从散列中找到表中项目的索引,这是一个需要O(1)的操作。@MosesKoledoye:我认为这不是O(1)<代码>查看索引是否在表中,即使使用哈希,也意味着迭代并查看它是否在表中。或者,您可以给出一个示例,说明如何在没有任何循环的情况下查看一个元素的大小是否为10000000000?(也许有什么我没有得到的…)
FOUND_FILES = [f for f in FILES if f[1] in I]
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