从RegEx'd字符串中查找字符位置

时间:2011-01-20 00:25:44

标签: python regex

说,我有'ABBACDA',我想找到每个A的位置索引。

在Python中使用Regex, match = re.findall('A', 'ABBACDA') 只返回一个列表。

我可以调整这个吗?或者我应该走一条完全不同的路线?我想避免使用for x in enumerate(str),因为我还想检查“BB”的位置以及从哪个索引开始。

6 个答案:

答案 0 :(得分:5)

使用re.finditer()

示例1:

match = re.finditer('A', 'ABBACDA')
for m in match:
    print m.start(), m.end(), m.group(0)

输出:

0 1 A
3 4 A
6 7 A

示例2:

match = re.finditer('BB', 'ABBACDA')
for m in match:
    print m.start(), m.end(), m.group(0)

输出:

1 3 BB

答案 1 :(得分:2)

致John Machin

«(1)在你的“查找”代码中,tof是“A”,在你的正则代码中,tof是“BB”»

没有。 有一个'find'代码,其中tof ='A', 并且有一个代码将'find'方法和'regex'方法与tof ='BB'进行比较。没有单独的'正则表达式'代码,tof ='BB'

'find'代码以一种孤立的方式呈现这个解决方案,以便更清楚,因为在第二个代码中,它的可见性是不可见的。

我将pat = re.compile(tof)的定义放在循环之外,以便不计算在测量时间内创建它的时间。正如它在第二个代码的开头,你相信它是一个完全'正则表达式'的代码。事实并非如此。这是一个比较代码。

你应该仔细阅读。

«(2)ch [prec:]。find(tof)而不是ch.find(tof,prec)»

实际上我已经知道索引必须放在find()中而不是在字符串中使用。我发现它并且我已经在过去的代码中使用过那种方式,但我脑子里只有一个空白。

顺便说一下,代码更简单。其次,正如您所指出的,更正的“查找”解决方案现在运行得更快。当正则表达式解决方案在0.77 * T(校正前0.65 * T)运行时,它在T秒内运行:

ch = 'jggBBjgjBBBjhgBBBBjjgBBBBBjjggBBBBBBjjjgjBBBBBBB'
tof = 'BB'
L = len(tof)

X,Y = [],[]
pat = re.compile(tof)

for essay in xrange(5):

    te = clock()
    for i in xrange(1000):
        li = []
        x = ch.find(tof)
        while x+1:
            li.append(x)
            x = ch.find(tof,x+L)
    X.append( clock()-te )


    te = clock()
    for i in xrange(1000):
        ly = [ m.start() for m in pat.finditer(ch) ]
    Y.append( clock()-te )

print li,'\n',ly,'\n'
print min(X),'\n',min(Y)

但它并没有那么显着的加速:快18%。

«(3)你的查找代码考虑重叠匹配,正则表达式代码没有»

我不这么认为。我正是用“ABBACDABBmmrteyBBgfrewBBBBBioBByt BBB ggddbBB BBbGtBBBGtbBbGT”包含“BBBBB”试图验证“发现”解决方案给出了相同的结果为“正则表达式”的解决方案,因为我知道,正则表达式不会返回重叠的匹配。我精确地使用L = len(tof)来避免检测重叠切片。

上述代码的结果:

[3, 8, 14, 16, 21, 23, 30, 32, 34, 41, 43, 45]
[3, 8, 14, 16, 21, 23, 30, 32, 34, 41, 43, 45]

那么“您的查找代码是否考虑重叠匹配”是什么意思?拜托,

«(4)等等»

这是不公平的。如果有etceterae,告诉哪些。如果没有......好吧,我不知道...

我认为1:1的比率对假的,一个可疑一个和一个不公平的一个右评论是不够的downvote。

此外,在我看来,写上的问题后1〜2小时,让不完美的答案,不逃避downvotes,而良好的相似者更很少upvoted因为questionner有他的解决方案很长一段时间

答案 2 :(得分:0)

如果您只查找一个结果,请改用re.search函数。 返回MatchObject(http://docs.python.org/library/re.html#re.MatchObject)。该对象具有start()和end()函数。

答案 3 :(得分:0)

您可以尝试对以下内容进行计时,看它是否比正则表达式更快:

def multifind(needle, haystack, overlap=False):
    delta = 1 if overlap else max(1, len(needle))
    pos = 0
    find = haystack.find
    while 1:
        pos = find(needle, pos)
        if pos < 0: return
        yield pos
        pos += delta

>>> data = 'ABBACDABBmmrteyBBgfrewBBBBBioBBytA BBB ggdAdbBB BBbGtBBABGtbBbGT'
>>> list(multifind('A', data))
[0, 3, 6, 33, 42, 55]
>>> list(multifind('BB', data))
[1, 7, 15, 22, 24, 29, 35, 45, 48, 53]
>>> list(multifind('BB', data, overlap=True))
[1, 7, 15, 22, 23, 24, 25, 29, 35, 36, 45, 48, 53]
>>> list(multifind('', 'qwerty'))
[0, 1, 2, 3, 4, 5, 6]
>>>

答案 4 :(得分:0)

哦,我也知道使用发电机,我忘记了它在这项研究中的优势。这是一个很好的评论,这个。

使用别名hayfind = haystack.find来提高代码速度也非常棘手。

现在'find with generator'方法在T中运行,'regex'方法仅在0.96 * T

运行
ch = 'jggBBjgjBBBjhgBBBBjjgBBBBBjjggBBBBBBjjjgjBBBBBBB'
tof = 'BB'
L = len(tof)

X,Y = [],[]
pat = re.compile(tof)

def multifind(needle, haystack):
    delta = len(needle)
    pos = 0
    hayfind = haystack.find
    while 1:
        pos = hayfind(needle, pos)
        if pos < 0:  return
        yield pos
        pos += delta

for essay in xrange(20):

    te = clock()
    for i in xrange(10000):
        li = list(multifind(tof,ch))
    X.append( clock()-te )


    te = clock()
    for i in xrange(10000):
        ly = [ m.start() for m in pat.finditer(ch) ]
    Y.append( clock()-te )

print li,'\n',ly,'\n'
print min(X),'\n',min(Y)

这两种方法具有相同的速度。但我最终更喜欢'正则表达式'解决方案,因为它可以被修改以在需要时获得更多结果(开始和结束,其他条件......),而'find'解决方案只给出位置。

答案 5 :(得分:-1)

我喜欢正则表达式,但我搜索了另一种解决方案:

ch = 'ABBACDABBmmrteyBBgfrewBBBBBioBBytA BBB ggdAdbBB BBbGtBBABGtbBbGT'
tof = 'A'

li, prec = [], 0
x = ch[prec:].find(tof)

while x+1:
    li.append(prec+x)
    prec += x+1
    x = ch[prec:].find(tof)

print li

结果

[0, 3, 6, 33, 42, 55]

我测量了速度,当使用find()的解决方案在T秒内运行时,使用正则表达式的解决方案在0,65 * T运行时我感到很惊讶:

ch = 'ABBACDABBmmrteyBBgfrewBBBBBioBByt BBB ggddbBB BBbGtBBBGtbBbGT'

tof = 'BB'

X,Y = [],[]
pat = re.compile(tof)

for essay in xrange(50):

    te = clock()
    for i in xrange(1000):
        li, prec, L = [], 0, len(tof)
        x = ch[prec:].find(tof)
        while x+1:
            li.append(prec+x)
            prec += x+L
            x = ch[prec:].find(tof)
    X.append( clock()-te )

    te = clock()
    for i in xrange(1000):
        ly = [ m.start() for m in pat.finditer(ch) ]
    Y.append( clock()-te )

print li
print ly
print
print min(X)
print min(Y)