2009-12-09 80 views
0

我在阅读字符串列表,其中每个字符串都与文件名有关。但是,每个字符串都是负号。我想出了下面的代码:如何使用re搜索Python中另一个列表中的一个列表中的项目

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”。话虽如此,有没有更好的方法来做到这一点?

谢谢。

+0

有用知道有多少项目在每两个列表,并且代码多久会被调用。 – Will 2009-12-09 07:31:25

+0

@我会说列表中会有数千个文件。该列表应该比目录中的实际文件数量稍大(5%左右)。 – Alex 2009-12-09 22:09:34

回答

2

您可以将所有的物品组合成一个正则表达式是这样,这将是更有效的

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函数解析文件名,尽管解析出基本名称并在集合中查找它们。

+0

如果这些项目可以包含像'.'这样的正则表达式 - 特殊标点符号,则在加入之前,您需要''item_list''中的每个项目're.escape'。 – bobince 2009-12-09 14:12:35

+0

感谢尼克,这篇文章值得一百个有用的投票!找到timeit模块并根据我的原始算法Dave Kirby算法和您的算法进行测试。结果如下: alex_k:15.93 dave_kirby:6.98 nick_craig_wood:0.24 – Alex 2009-12-10 00:16:05

0

这里的另一种方式做到这一点很可能快于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)) 
2

使用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 +'。')。

+0

+1表示splitext。准确地做它说的;比正则表达式更可读。 – bobince 2009-12-09 14:27:57

0

我认为你应该使用.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')] 

或与循环

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

你并不需要使用正则表达式为这一点,因为你正在做详细的字符串匹配(不含通配符,团体等) - 您可以使用str.startswith (..)。这相当于代码:

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

但是所有的比赛编译成一个单一的正则表达式会更有效的尼克·克雷格 - 伍德的建议 - 我建议你两个基准如果速度是一个问题。

+0

任何帮助基准的工具/命令都是+1! – Alex 2009-12-09 22:32:25

0
>>> 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')] 
>>> 

不需要正则表达式。

1

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

马克·拜尔斯的答案重复保留matchesitem_list-order的原始行为。如果你不需要,你可以做到这一点更简单/快:

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

如果您不需要保持(item)匹配的是(因为它是从文件名反正多余的),你有一个班轮:

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

他们确实需要匹配,但谢谢你给出了一个很好的例子! – Alex 2009-12-09 22:51:50

相关问题