如何在Python中使用re在一个列表中搜索另一个列表中的项目

如何在Python中使用re在一个列表中搜索另一个列表中的项目,python,regex,Python,Regex,我正在阅读一个字符串列表,每个字符串都与文件名有关。但是,每个字符串都减去扩展名。我想出了以下代码: import re item_list = ['item1', 'item2'] search_list = ['item1.exe', 'item2.pdf'] matches = [] for item in item_list: # Match item in search_list using re - I assume this is the best way to do th

我正在阅读一个字符串列表,每个字符串都与文件名有关。但是,每个字符串都减去扩展名。我想出了以下代码:

import re
item_list = ['item1', 'item2']
search_list = ['item1.exe', 'item2.pdf']
matches = []
for item in item_list:
    # Match item in search_list using re - I assume this is the best way to do this
    regex = re.compile("^"+item+"\.")
    for file in search_list:
        if regex.match(file):
            matches.append((item, file))
至于重复匹配,我并不担心两个文件被命名为'foo.bar'和'foo.foo.bar'。也就是说,有没有更好的方法


谢谢。

这里有另一种可能比Alex的原始代码更快的方法:

item_list = ['item1', 'item2']
search_list = ['item1.exe', 'item2.pdf']
matches = []
for item in item_list:
    for filename in search_list:
        if filename.partition(".")[0] == item:
            matches.append((item,filename))

下面是另一种可能比Alex的原始代码更快的方法:

item_list = ['item1', 'item2']
search_list = ['item1.exe', 'item2.pdf']
matches = []
for item in item_list:
    for filename in search_list:
        if filename.partition(".")[0] == item:
            matches.append((item,filename))

您可以像这样将所有项合并到一个regexp中,这样会更有效

import re
item_list = ['item1', 'item2']
regex = re.compile("^("+"|".join(item_list)+")\.")
search_list = ['item1.exe', 'item2.pdf']
matches = []
for file in search_list:
    match = regex.match(file)
    if match:
        matches.append((match.group(1), file))

更好的解决方案可能是使用os.path函数解析文件名,但要解析出基名并在一组中查找它们。

您可以将所有项组合成一个这样的regexp,这样会更有效

import re
item_list = ['item1', 'item2']
regex = re.compile("^("+"|".join(item_list)+")\.")
search_list = ['item1.exe', 'item2.pdf']
matches = []
for file in search_list:
    match = regex.match(file)
    if match:
        matches.append((match.group(1), file))

更好的解决方案可能是使用os.path函数解析文件名,但要解析出基本名称并在集合中查找它们。

使用splitext获取不带扩展名的文件名:

import os.path

for item in item_list:
    for filename in search_list:
        if item == os.path.splitext(filename)[0]:
            matches.append((item, file))

这更正确,但也更容易理解阅读代码的意图。或者,如果要允许foo与foo.bar.txt匹配,请改用filename.startswith(item+')。

使用splitext获取不带扩展名的文件名:

import os.path

for item in item_list:
    for filename in search_list:
        if item == os.path.splitext(filename)[0]:
            matches.append((item, file))

这更正确,但也更容易理解阅读代码的意图。或者,如果您想允许foo与foo.bar.txt匹配,那么可以使用filename.startswith(item+')。

我认为您应该使用
.rsplit(“.”,1)
出于这个目的,正则表达式是否过了头

>>> item_list = ['item1', 'item2','item3']
>>> search_list = ['item1.exe', 'item2.pdf','item9999.txt']
>>>
>>> [(x.rsplit(".",1)[0],x) for x in search_list if x.rsplit(".",1)[0] in item_list]
[('item1', 'item1.exe'), ('item2', 'item2.pdf')]
或者使用for循环

matches=[]
for x in search_list:
    y=x.rsplit(".",1)[0]
    if y in item_list:
        matches.append((y,x))

我认为您应该使用
.rsplit(“.”,1)
出于这个目的,正则表达式没有被过度使用吗

>>> item_list = ['item1', 'item2','item3']
>>> search_list = ['item1.exe', 'item2.pdf','item9999.txt']
>>>
>>> [(x.rsplit(".",1)[0],x) for x in search_list if x.rsplit(".",1)[0] in item_list]
[('item1', 'item1.exe'), ('item2', 'item2.pdf')]
或者使用for循环

matches=[]
for x in search_list:
    y=x.rsplit(".",1)[0]
    if y in item_list:
        matches.append((y,x))

您不需要使用正则表达式,因为您正在进行精确的字符串匹配(没有通配符、组等)-您可以使用str.startswith(..)。这相当于您的代码:

for item in item_list:
    match = item + "."
    for file in search_list:
        if file.startswith(match)
            matches.append((item, file))

然而,尼克·克雷格·伍德(Nick Craig Wood)提出的将所有匹配项编译成一个正则表达式的建议可能更有效——如果速度有问题,我建议您对两者进行基准测试。

您不需要使用正则表达式,因为您正在进行精确的字符串匹配(没有通配符、组等)——您可以使用str.startswith(…)。这相当于您的代码:

for item in item_list:
    match = item + "."
    for file in search_list:
        if file.startswith(match)
            matches.append((item, file))
>>> for file in search_list:
...  tomatch=file.split(".")[0]
...  if tomatch in item_list:
...     found=item_list.index(tomatch)
...     matches.append( ( file, item_list[found] ) )
...
>>> print matches
[('item1.exe', 'item1'), ('item2.pdf', 'item2')]
>>>
然而,尼克·克雷格·伍德(Nick Craig Wood)建议将所有匹配项编译成一个正则表达式可能更有效——如果速度是一个问题,我建议您对这两种方法进行基准测试

>>> for file in search_list:
...  tomatch=file.split(".")[0]
...  if tomatch in item_list:
...     found=item_list.index(tomatch)
...     matches.append( ( file, item_list[found] ) )
...
>>> print matches
[('item1.exe', 'item1'), ('item2.pdf', 'item2')]
>>>
不需要正则表达式


不需要正则表达式。

避免
re
,除非你真的需要它。对于简单的字符串匹配,您实际上并不需要它

Mark Byers的回答重复了将
匹配项保持在
项目列表中的原始行为。如果您不需要,您可以更简单/快速地完成:

for file in search_list:
    item= os.path.splitext(file)[0]
    if item in item_list:
        matches.append((item, file))
如果您不需要保持
(项)
匹配(因为它在文件名中是多余的),那么您有一行代码:

matches= [file for file in search_list if os.path.splitext(file)[0] in item_list]

除非你真的需要,否则不要重复。对于简单的字符串匹配,您实际上并不需要它

Mark Byers的回答重复了将
匹配项保持在
项目列表中的原始行为。如果您不需要,您可以更简单/快速地完成:

for file in search_list:
    item= os.path.splitext(file)[0]
    if item in item_list:
        matches.append((item, file))
如果您不需要保持
(项)
匹配(因为它在文件名中是多余的),那么您有一行代码:

matches= [file for file in search_list if os.path.splitext(file)[0] in item_list]

了解两个列表中每个列表中有多少项以及调用代码的频率非常有用。@will,我想说列表中有数千个文件。列表应该比目录中的实际文件数略大(5%左右)。了解两个列表中的每个项目以及调用代码的频率非常有用。@will,我想说列表中有数千个文件。该列表应该比目录中的实际文件数稍大(5%左右)。如果项目可以包含正则表达式特殊标点符号,如
,则在加入之前,您需要
重新转义
项目列表中的每个项目。谢谢尼克,这篇文章值得100次有用的投票!找到timeit模块并基于我的原始算法、Dave Kirby算法和您的算法运行测试。结果如下:alex_k:15.93 dave_kirby:6.98 nick_craig_wood:0.24如果项目可以包含regex特殊标点符号,如
,则在加入之前,您需要
re.escape
退出
项目列表中的每个项目。谢谢nick,这篇文章值得100次有用的投票!找到timeit模块并基于我的原始算法、Dave Kirby算法和您的算法运行测试。结果如下:alex_k:15.93 dave_kirby:6.98 nick_craig_wood:0.24+1表示splitext。言行一致;对于splitext,比正则表达式+1可读性更强。言行一致;比正则表达式更可读。它们确实需要匹配,但感谢您提供了一个单行程序的好例子!它们确实需要匹配,但感谢您提供了一个单行程序的好例子!