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 来完成,但似乎有点复杂。我可以写一个原始循环,但这似乎不是特别有效。
关于如何处理此类匹配问题的任何建议。
您可以按照您的建议 运行 a 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
以下版本更快,大约 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
您还可以通过对照 None
.
检查当前 res[name]
值来保留第一个匹配项
这道题是关于在一个列表中用匹配的字符串匹配字符串 在另一个列表中。我试图找出进行这种匹配的最佳方法。我下面的示例很小,但我必须将相同的想法应用于更大的列表。所以我在一个列表中有一组文件名和路径, 然后我在另一个列表中有一个部分文件名列表,对于 示例:
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 来完成,但似乎有点复杂。我可以写一个原始循环,但这似乎不是特别有效。
关于如何处理此类匹配问题的任何建议。
您可以按照您的建议 运行 a 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
以下版本更快,大约 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
您还可以通过对照 None
.
res[name]
值来保留第一个匹配项