【问题标题】:Search for files for which dirname has a certain pattern搜索 dirname 具有特定模式的文件
【发布时间】:2017-12-01 12:58:47
【问题描述】:

假设我们有 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的索引,其中包含AB

    I = [i for i in range(len(DIRS)) if 'AB' in DIRS[i]]          # here [1, 2, 4]
                                                                  # but can be of size 1000
    

    我们只在DIRS上循环一次,也就是100k,没关系

  • (2) 现在我们需要在 I(例如可以是 1000)和 FILES(即 100 万)上循环,而 这太多了,因为 1000 * 1M = 10 亿次操作:

    FOUND_FILES = []
    for i in I:
        for f in FILES:
            if f[1] == i:
                FOUND_FILES.append(f)
    

这操作太多了! 如何在保持DIRS / FILES 数据结构的同时进行更高效的研究?(如果100% 完全不可能,我应该考虑哪种其他结构?)


注意:(2)的这个替代方案并没有加快我认为的任何事情:

for f in FILES:      # we loop over 1M items
    if f[1] in I:    # to test if f[1] is contained in I, we might loop over 1000 items too
        FOUND_FILES.append(f)

【问题讨论】:

    标签: python list loops optimization filesystems


    【解决方案1】:

    如果您将I 设置为一组,则替代方法的时间复杂度可以降低到O(n)(其中nFILES 的长度) ,而不是原来的 O(n*m)(其中 mI 的长度):

    I = {i for i, x in enumerate(DIRS) if 'AB' in x}
    

    集合的一个重要用途是快速成员查找; O(1).

    您还可以通过使用列表解析来构建最终的FOUND_FILES 列表,从而获得一些显着的 CPU 时间:

    FOUND_FILES = [f for f in FILES if f[1] in I]
    

    如果您通过读取父目录的全部内容来构建文件列表,例如使用os.listdir,则应改为应用glob.glob,以直接从您的模式构建列表。

    【讨论】:

    • One of the important uses of a set is fast membership lookup; O(1) 这怎么可能?集合越大,成员查找越慢,不是吗?所以“set size”和“membership lookup time”应该是成正比的,你不这么认为吗?
    • @Basj 不,理想情况下。集合使用哈希表,因此它们不需要按顺序迭代项目。足以从其散列中找到该项目在表中的索引,该操作需要 O(1)。
    • @MosesKoledoye:我认为这不是 O(1)。 Looking if an index is in a table,即使使用散列,也意味着迭代并查看它是否存在。或者,也许您可​​以举个例子,展示如何在没有任何循环的情况下查看一个元素是否在大小为 100000000000 的集合中? (也许有些东西我没有得到......)
    【解决方案2】:
    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
    

    喜欢这样吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      相关资源
      最近更新 更多