添加re.finditer结果

时间:2013-12-05 15:53:57

标签: python regex

无论如何,你可以使用findall来添加来自不同发现者的结果吗?例如:

matches = re.finditer(pattern_1, text) + re.finditer(pattern_2, text)

我有几种不同的模式和结果,我想将它们作为单个块而不是单独进行迭代。

4 个答案:

答案 0 :(得分:5)

您可以使用itertools.chain.from_iterable

from itertools import chain

patterns = [] # All patterns go here

for match in chain.from_iterable(re.finditer(pattern, text) for pattern in patterns):
    print match

这会产生

<_sre.SRE_Match object at 0x021544B8>
<_sre.SRE_Match object at 0x021544F0>
<_sre.SRE_Match object at 0x021544B8>
<_sre.SRE_Match object at 0x021544F0>
<_sre.SRE_Match object at 0x021544B8>

使用equem的回答输入。

答案 1 :(得分:4)

您可以使用itertools.chain

import itertools

for match in itertools.chain(re.finditer(pattern_1, text), re.finditer(pattern_2, text)):
    pass

答案 2 :(得分:3)

有一个模块chain from itertools
您可以创建一个迭代器,它从第一个到最后一个返回可迭代对象的所有元素

import itertools 
matches = itertools.chain(re.finditer(pattern_1, text),re.finditer(pattern_2, text))
for m in matches:
    pass

通常itertools是礼物。

答案 3 :(得分:2)

它不是您需要的发电机功能,
而不是链接生成器re.finditer(pat,text),你将不得不为每个生成器使用不同的模式一个接一个地编写,并为每个新模式组重新执行相同的任务?

这是我的方式:

import re

pat1 = '<tag>.+?</tag>'
pat2 = 'mount.+?@'
pat3 = '\d{3} [a-r]+'

text = 'The amount <tag>of 100 dollars was</tag> given @ me'\
       '<tag>the_mountain_and_desert : john@gmail.com'\
       'Sun is mounting @ the top of the sky'


def gmwp(text,patterns): #generates matches with patterns
    for pat in patterns:
        for m in re.finditer(pat,text):
            yield m.group() 

ps = (pat1,pat2,pat3)

for x in gmwp(text,ps):
    print x

结果

<tag>of 100 dollars was</tag>
mount <tag>of 100 dollars was</tag> given @
mountain_and_desert : john@
mounting @
100 dollar

关键字yield的存在将函数定义为生成函数。

修改

因此,对于Steinar Lima的评论,我再次检查了这个问题。

从某种意义上说,Steinar Lima是对的,我编写的函数有点像itertools.chains()执行的链接。但事实并非如此。

实际上,我的生成器函数不会像基于chain()的其他解决方案那样产生匹配;它在文本中产生匹配的子串,因为在我看来,如果有人想要使用正则表达式,那就是在文本中找到匹配的子串,而不是匹配。所以这个函数用于匹配chain()为其他解决方案中的匹配所做的子串,但因为我没有成功地用chain()来做,我认为不可能找到一个使用chain()产生我的生成器函数的解决方案,我并不完全同意他的观点,即我写了另一个chain()的实现:为了我的特定目标,使用chain()是不切实际的。如果可以,请告诉我。

现在,如果目的是找到一种方法来从一组模式中产生匹配:

  • Simeon Visser和Deck编写的代码并不让我高兴,因为它要求我们为每个正则表达式模式编写re.finditer(pattern_1, text), re.finditer(pattern_2, text), etc,而不仅仅是它们的集合。

  • Steinar Lima的代码使用了这样的集合,但它不再让我高兴,因为它返回匹配的迭代器,而不是匹配。

  • 在将我的想法付诸命令后,我发现了我认为真正方便的解决方案:
    我的第二个代码使用chain()和集合patterns来产生Match对象的让步。

import re
from pprint import pprint

text = 'The amount <tag>of 100 dollars was</tag> given @ me'\
       '<tag>the_mountain_and_desert : john@gmail.com'\
       'Sun is mounting @ the top of the sky'

pattern_1 = '<tag>.+?</tag>'
pattern_2 = 'mount.+?@'
pattern_3 = '\d{3} [a-r]+'

print 'Code of #Simeon Visser and Deck========='
import itertools
for match in itertools.chain(re.finditer(pattern_1, text),
                             re.finditer(pattern_2, text),
                             re.finditer(pattern_3, text)):
    print match # a Match object
    #pprint(list(match))

print '\nCode of #Steinar Lima =================='
from itertools import chain
patterns = [pattern_1,pattern_2,pattern_3] # All patterns go here
for match in chain(re.finditer(pattern, text) for pattern in patterns):
    print '# ',match # a re.finditer(...) iterator object
    pprint(list(match))


print '\nCode 2 of #eyquem ======================'
for match in chain(*(re.finditer(pattern, text)
                     for pattern in patterns)):
    print match # a Match object

结果

Code of #Simeon Visser and Deck=========
<_sre.SRE_Match object at 0x011DB800>
<_sre.SRE_Match object at 0x011DB838>
<_sre.SRE_Match object at 0x011DB800>
<_sre.SRE_Match object at 0x011DB838>
<_sre.SRE_Match object at 0x011DB800>

Code of #Steinar Lima ==================
#  <callable-iterator object at 0x011E0B10>
[<_sre.SRE_Match object at 0x011DB800>]
#  <callable-iterator object at 0x011E0A90>
[<_sre.SRE_Match object at 0x011DB800>,
 <_sre.SRE_Match object at 0x011DB838>,
 <_sre.SRE_Match object at 0x011DB870>]
#  <callable-iterator object at 0x011E0B10>
[<_sre.SRE_Match object at 0x011DB800>]

Code 2 of #eyquem ======================
<_sre.SRE_Match object at 0x011DB800>
<_sre.SRE_Match object at 0x011DB838>
<_sre.SRE_Match object at 0x011DB800>
<_sre.SRE_Match object at 0x011DB838>
<_sre.SRE_Match object at 0x011DB800>

编辑2

因此,在修改之后,Steinar Lima的代码产生与我自己的第二个代码相同的结果。

我在使用chain(*(........))

时使用chain.from_iterable(.........)

我想知道是否有任何差异可以证明最好使用这两种方式中的一种

以下代码比较执行的时间。

from time import clock

n = 5000

print '\nCode 2 of #eyquem ======================'
te = clock()
for i in xrange(n):
    for match in chain(*(re.finditer(pattern, text)
                         for pattern in patterns)):
        del match
t1 = clock()-te
print t1


print '\nCode 2 of #Steinar Lima ================'
te = clock()
for i in xrange(n):
    for match in chain.from_iterable(re.finditer(pattern, text)
                                     for pattern in patterns):
        del match
t2 = clock()-te
print t2

print '\ntLima/teyquem == {:.2%}'.format(t2/t1)
  • 似乎两个代码中哪一个更快取决于n的值,无论如何,从一个代码到另一个代码的时间差异不大

  • 事实上,我的方式使用的字母少于chain.from_iterable使用的字母,但它不是决定因素。

  • 另一点是,在个人方面,我更容易理解chain(*(........))形式:它立即表示操作采用(.........)中的每个序列并一个接一个地链接所有元素。
    虽然chain.from_iterable(.........)给我的印象是(..........)中的序列是一个接一个地产生的,而不是它们的元素。
    这是主观的。

  • 我发现只有一个案例,其中函数chain.from_iterable具有特定的优势,当有人希望对集合中存在的几个序列序列执行操作时。
    以下代码显示了我的意思

from pprint import pprint
from itertools import chain

li = [(1,12,85),'king',('a','bnj')]
hu = (['AB',pprint],(145,854))
ss = 'kim'

collek = (li,hu,ss)
print 'collek :'
pprint(collek)

print

for x in  map(chain.from_iterable,collek):
    print list(x),x

print

for y in collek:
    print list(chain(*y))

结果

collek :
([(1, 12, 85), 'king', ('a', 'bnj')],
 (['AB', <function pprint at 0x011DDFB0>], (145, 854)),
 'kim')

[1, 12, 85, 'k', 'i', 'n', 'g', 'a', 'bnj']
['AB', <function pprint at 0x011DDFB0>, 145, 854]
['k', 'i', 'm']

[1, 12, 85, 'k', 'i', 'n', 'g', 'a', 'bnj']
['AB', <function pprint at 0x011DDFB0>, 145, 854]
['k', 'i', 'm']

第一次迭代产生的对象是直接迭代器,而在第二次迭代中,产生的对象是集合的元素,之后必须应用链接。
第二次迭代可以写成:

for y in collek:
    print list(chain.from_iterable(y))

但第一个不能用其他方式写。