我正在为一个项目解析超过两百万个文本文件,需要你的正则表达式帮助加快速度。我需要拆分单词,以便我能够使用:
text_file = re.sub(r'\W+',' ', text_file)
然而,对于带连字符的单词,我想删除连字符,但结合这个词(即非营利组织将是非营利组织而非“非”组织,“利润”)。目前,我能够通过两次搜索和替换(完全不理想)来做到这一点。最终输出将是collections.Counter()对象使用的单词列表。
def mod1(text_file):
text_file = re.sub('\s*-\s*', '', text_file) # handling hyphens :( O(n)
text_file = re.sub(r'\W+',' ', text_file)
text_file = text_file.lower()
return(text_file)
除了正则表达式之外,任何更快的处理提示都会非常感激。感谢。
答案 0 :(得分:1)
使用lower()
后,您可以使用re.sub(r'([a-z])-([a-z])', r'\1\2', s)
删除连字符。
然后re.split(r'[^a-z]')
,分开单词。
s = s.lower()
s = re.sub(r'([a-z])-([a-z])', r'\1\2', s)
s = re.split(r'[^a-z]', s)
此解决方案可能(或可能不)更快,具体取决于上使用的文本。它确实有一些可能的加速:
[a-z]
代替\w
。lower()
,允许re.sub()
搜索一半字母;这是[a-z]
而不是[A-Za-z]
。'\s*-\s*'
替换[a-z]-[a-z]
答案 1 :(得分:0)
你可以这样做,
>>> s = 'non-profit foo:?bar/buzz'
>>> ''.join(re.sub(r'\W+', ' ',i.strip()) for i in s.split('-'))
'nonprofit foo bar buzz'
OR
您可以在re.sub
的替换部分中定义一项功能。
>>> s = 'non-profit foo:?bar/buzz'
>>> re.sub(r'\W+', lambda m: re.sub(r'.*', '', m.group(0)) if re.match(r'\s*-\s*$', m.group(0)) else re.sub(r'.*', r' ', m.group(0)), s)
'nonprofit foo bar buzz'
OR
保持简单......
>>> re.sub(r'\W+', lambda m: '' if re.match(r'\s*-\s*$', m.group(0)) else ' ', s)
'nonprofit foo bar buzz'
此代码将替换每个创建的匹配项。也就是说,在每次匹配之后,调用函数m。 \W+
匹配一个或多个非字字符。如果找到匹配,如果matchobject.group(0)满足此\s*-\s*$
条件,则它将返回空字符串,否则它将返回单个空格字符串。这就是匹配被替换为返回值。
答案 2 :(得分:0)
您可以使用str.translate
方法,该方法比regex
更快:
>>> import string
>>> s ='aslkdf - sadlk#gjf'
>>> s.translate(str.maketrans(string.punctuation,32*' ','-'+string.whitespace))
'aslkdfsadlk gjf'
答案基准:
#Avinash Raj
:~$ python3 -m timeit "import re;s='aslkdf - sadlk#gjf';re.sub(r'\W+', lambda m: '' if re.match(r'\s*-\s*$', m.group(0)) else ' ', s)"
100000 loops, best of 3: 7.96 usec per loop
#Kasra
:~$ python3 -m timeit "import string;s='aslkdf - sadlk#gjf';s.translate(str.maketrans(string.punctuation,32*' ','-'+string.whitespace))"
100000 loops, best of 3: 4.75 usec per loop
#user 5061
:~$ python3 -m timeit "import re;s='aslkdf - sadlk#gjf';s=s.lower();s = re.sub(r'([a-z])-([a-z])', r'\1\2', s);re.split(r'[^a-z]', s)"
100000 loops, best of 3: 8.46 usec per loop