簡體   English   中英

加總篩選結果

[英]Adding up re.finditer results

無論如何,是否有可能像findall一樣將不同Finditer的結果相加? 例如:

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

我有幾種不同的模式和結果,我想將它們作為一個單獨的塊而不是單獨的塊進行迭代。

您可以使用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>

使用來自等值答案的輸入。

您可以使用itertools.chain

import itertools

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

itertools提供了一個模塊
您可以創建一個迭代器,該迭代器從第一個到最后一個返回可迭代對象的所有元素

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

通常, itertools是禮物。

這不是您需要的生成器函數嗎?
而不是鏈接生成器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 ,因為它要求我們為每個正則表達式模式(不僅是它們的集合re.finditer(pattern_1, text), re.finditer(pattern_2, text), etc編寫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))

但是第一個不能用其他方式寫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM