簡體   English   中英

Python3:基於子字符串匹配兩個列表之間的元素

[英]Python3: Matching elements between two lists based upon substrings

這個問題是關於將一​​個列表中的字符串與另一個列表中的匹配字符串進行匹配。 我試圖找出進行這種匹配的最佳方法。 我下面的示例很小,但我必須將相同的想法應用於更大的列表。 所以我在一個列表中有一組文件名和路徑,然后在另一個列表中有一個部分文件名列表,例如:

    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 或 10,000 個條目的列表最有效。 似乎這可以通過字典理解或 lambda 來完成,但似乎有點復雜。 我可以編寫一個原始循環,但這似乎不是特別有效。

有關如何管理此類匹配問題的任何建議。

您可以按照您的建議運行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'}

推導式只是編寫集合構建循環的一種更簡單的方法。 簡單易懂,不一定高效。

在@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) ]

dict comprehension在我的機器上大約需要 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

以下版本速度更快,大約為 1ms:

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來保持第一個匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM