代码之家  ›  专栏  ›  技术社区  ›  krishnab

python3:基于子字符串在两个列表之间匹配元素

  •  0
  • krishnab  · 技术社区  · 7 年前

    这个问题是关于在一个列表中用匹配的字符串匹配字符串 在另一个列表中。我想找出最好的匹配方法。我下面的例子很小,但我必须将同样的想法应用到更大的列表中。所以我在一个列表中有一组文件名和路径, 然后我在另一个列表中有一个部分文件名的列表 例子:

        list1 = ['/../../abc_file1.txt',
                 '/../../abc_extrafile1.txt',
                 '/../../abc_file2.txt',
                 '/../../abc_file3.txt',
                 '/../../abc_extrafile3.txt']
    

    然后我有一个不同的清单

        ['file1', 'extrafile1', 'file2', 'file3', 'extrafile3']
    

    所以我想做的是得到一个匹配,生成一个字典,比如:

        {'file1': '/../../abc_file1.txt',
         'extrafile1': '/../../abc_extrafile1.txt',
         'file2': '/../../abc_file2.txt',
         'file3': '/../../abc_file3.txt',
         'extrafile3': '/../../abc_extrafile3.txt'}
    

    所以文件名之间有些重叠,我需要 小心点。

    有很多方法可以做到这一点,但我不确定哪种方法最适合匹配1000或10000个条目的列表似乎这可以通过字典理解或lambda来完成,但似乎有点复杂。我可以写一个原始循环,但这似乎不是特别有效。

    关于如何处理此类匹配问题的任何建议。

    1 回复  |  直到 7 年前
        1
  •  1
  •   DirtyBit    7 年前

    你可以运行一个 dict comprehension 正如你所建议的,检查一下 split 第一个列表元素(考虑到重叠)和删除扩展名:

    list1 = ['/../../abc_file1.txt',
                 '/../../abc_extrafile1.txt',
                 '/../../abc_file2.txt',
                 '/../../abc_file3.txt',
                 '/../../abc_extrafile3.txt']
    
    list2 = ['file1', 'extrafile1', 'file2', 'file3', 'extrafile3']
    
    my_dict = {k: v for v in list1 for k in list2 if k == v.split('_')[1][:-4]}
    

    输出 以下内容:

    {'file1': '/../../abc_file1.txt', 'extrafile1': '/../../abc_extrafile1.txt', 'file2': '/../../abc_file2.txt', 'file3': '/../../abc_file3.txt', 'extrafile3': '/../../abc_extrafile3.txt'}
    
        2
  •  0
  •   guillaume.deslandes    7 年前

    理解只是编写集合构建循环的一种简单方法。容易看,不一定有效。

    在@matt-b答案中, dict comprehension 隐藏双精度 for 循环,使理解相当慢的大名单(n平方复杂度)。

    你的特定问题可以用简单的循环来解决,保持复杂性的线性。

    使用此输入:

    size = 1000
    list1 = [ '/../../abc_file' + str(i) + '.txt' for i in range(size) ]
    list2 = [ 'file' + str(i) for i in range(size) ]
    

    这个 听写理解 在我的机器上大约需要500毫秒:

    my_dict = {k: v for v in list1 for k in list2 if k == v.split('_')[1][:-4]}
    
    # 1 loop, best of 3: 516 ms per loop
    

    以下版本的速度更快,大约为1毫秒:

    res = { k: None for k in list2 }
    for v in list1:
        name = v.split('_')[-1][:-4]
        if name in res:
            res[name] = v
    
    # 100 loops, best of 3: 1.15 ms per loop
    

    使用此结构,可以在需要时轻松保持多个匹配:

    res = { k: [] for k in list2 }
    for v in list1:
        name = v.split('_')[-1][:-4]
        if name in res:
            res[name].append(v)
    
    # 100 loops, best of 3: 1.54 ms per loop
    

    你也可以通过检查当前的 res[name] 价值观 None .