![](/img/trans.png)
[英]Creating a new list based on matching elements of two nested lists in Python?
[英]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.