【问题标题】:Using a function as argument to re.sub in Python?在 Python 中使用函数作为 re.sub 的参数?
【发布时间】:2016-05-21 03:15:39
【问题描述】:

我正在编写一个程序来拆分标签中包含的单词。

例如我想拆分主题标签:

#Whatthehello #goback

进入:

What the hello go back

我在使用带有函数参数的re.sub 时遇到了麻烦。

我写的代码是:

import re,pdb

def func_replace(each_func):
    i=0
    wordsineach_func=[] 
    while len(each_func) >0:
        i=i+1
        word_found=longest_word(each_func)
        if len(word_found)>0:
            wordsineach_func.append(word_found)
            each_func=each_func.replace(word_found,"")
    return ' '.join(wordsineach_func)

def longest_word(phrase):
    phrase_length=len(phrase)
    words_found=[];index=0
    outerstring=""
    while index < phrase_length:
        outerstring=outerstring+phrase[index]
        index=index+1
        if outerstring in words or outerstring.lower() in words:
            words_found.append(outerstring)
    if len(words_found) ==0:
        words_found.append(phrase)
    return max(words_found, key=len)        

words=[]
# The file corncob_lowercase.txt contains a list of dictionary words
with open('corncob_lowercase.txt') as f:
    read_words=f.readlines()

for read_word in read_words:
    words.append(read_word.replace("\n","").replace("\r",""))

例如当像这样使用这些函数时:

s="#Whatthehello #goback"

#checking if the function is able to segment words
hashtags=re.findall(r"#(\w+)", s)
print func_replace(hashtags[0])

# using the function for re.sub
print re.sub(r"#(\w+)", lambda m: func_replace(m.group()), s)

我得到的输出是:

What the hello
#Whatthehello #goback

这不是我预期的输出:

What the hello
What the hello go back

为什么会这样?特别是我使用了this answer 的建议,但我不明白这段代码出了什么问题。

【问题讨论】:

  • 嗯.. 有什么问题。为什么投反对票?这是关于编程!
  • 综合性很好,但您的问题至少应该是可读的。使用英语句子而不是像“aim: do this. Code: ..; output ..; why?see here”这样的摘要。
  • @Bakuriu 感谢您的编辑!我会记住再问一次。
  • 我只是想举例说明如何写一个好问题。你在提供完整的代码以及你所期望的输出方面做得很好,但是你应该至少放一段文字来描述你想要做什么(也许是为什么,一点背景)以及代码如何适应这个。这样你的问题会更有吸引力,更有用。

标签: python regex string replace hashtag


【解决方案1】:

注意m.group() 返回匹配的整个字符串,无论它是否属于捕获组:

In [19]: m = re.search(r"#(\w+)", s)

In [20]: m.group()
Out[20]: '#Whatthehello'

m.group(0) 也返回整个匹配:

In [23]: m.group(0)
Out[23]: '#Whatthehello'

相比之下,m.groups() 返回所有捕获组:

In [21]: m.groups()
Out[21]: ('Whatthehello',)

m.group(1) 返回第一个捕获组:

In [22]: m.group(1)
Out[22]: 'Whatthehello'

所以你的代码中的问题源于在

中使用m.group
re.sub(r"#(\w+)", lambda m: func_replace(m.group()), s)

因为

In [7]: re.search(r"#(\w+)", s).group()
Out[7]: '#Whatthehello'

如果你使用.group(1),你会得到

In [24]: re.search(r"#(\w+)", s).group(1)
Out[24]: 'Whatthehello'

而前面的# 则完全不同:

In [25]: func_replace('#Whatthehello')
Out[25]: '#Whatthehello'

In [26]: func_replace('Whatthehello')
Out[26]: 'What the hello'

因此,将m.group() 更改为m.group(1),并将/usr/share/dict/words 替换为corncob_lowercase.txt

import re

def func_replace(each_func):
    i = 0
    wordsineach_func = []
    while len(each_func) > 0:
        i = i + 1
        word_found = longest_word(each_func)
        if len(word_found) > 0:
            wordsineach_func.append(word_found)
            each_func = each_func.replace(word_found, "")
    return ' '.join(wordsineach_func)


def longest_word(phrase):
    phrase_length = len(phrase)
    words_found = []
    index = 0
    outerstring = ""
    while index < phrase_length:
        outerstring = outerstring + phrase[index]
        index = index + 1
        if outerstring in words or outerstring.lower() in words:
            words_found.append(outerstring)
    if len(words_found) == 0:
        words_found.append(phrase)
    return max(words_found, key=len)

words = []
# corncob_lowercase.txt contains a list of dictionary words
with open('/usr/share/dict/words', 'rb') as f:
    for read_word in f:
        words.append(read_word.strip())
s = "#Whatthehello #goback"
hashtags = re.findall(r"#(\w+)", s)
print func_replace(hashtags[0])
print re.sub(r"#(\w+)", lambda m: func_replace(m.group(1)), s)

打印

What the hello
What the hello gob a c k

因为,唉,'gob''go' 长。


您可以对此进行调试的一种方法是将lambda 函数替换为常规函数,然后添加打印语句:

def foo(m):
    result = func_replace(m.group())
    print(m.group(), result)
    return result

In [35]: re.sub(r"#(\w+)", foo, s)
('#Whatthehello', '#Whatthehello')   <-- This shows you what `m.group()` and `func_replace(m.group())` returns
('#goback', '#goback')
Out[35]: '#Whatthehello #goback'

这会让你的注意力集中在

In [25]: func_replace('#Whatthehello')
Out[25]: '#Whatthehello'

然后您可以与之比较

In [26]: func_replace(hashtags[0])
Out[26]: 'What the hello'

In [27]: func_replace('Whatthehello')
Out[27]: 'What the hello'

那你会问,如果m.group()返回'#Whatthehello',我需要什么方法返回'Whatthehello'。深入了解the docs 即可解决问题。

【讨论】:

  • 谢谢!这是迄今为止我读过的最好的解释答案。
  • 使用解释器一步一步解释问题真是太棒了。谢谢。一旦你理解了问题,解决方案就会跳到你身上。此外,您可以将您所了解的内容带到您未来的编码工作中。
猜你喜欢
  • 1970-01-01
  • 2012-08-20
  • 2013-05-11
  • 2012-10-09
  • 2013-09-15
  • 2011-06-26
  • 2011-09-11
  • 2017-05-21
  • 2020-07-13
相关资源
最近更新 更多