Python,从字符串中删除所有非字母字符


90

我正在编写python MapReduce字数统计程序。问题是数据中散布着许多非字母字符,我发现这篇文章从Python的字符串中剥离了除了字母数字字符之外的所有内容,这显示了使用正则表达式的一个很好的解决方案,但是我不确定如何实现它

def mapfn(k, v):
    print v
    import re, string 
    pattern = re.compile('[\W_]+')
    v = pattern.match(v)
    print v
    for w in v.split():
        yield w, 1

恐怕我不确定该如何使用该库re甚至正则表达式。我不确定如何将正则表达式模式v正确地应用于传入的字符串(书的一行)以检索没有任何非字母数字字符的新行。

有什么建议吗?


v是一本书的整行(特别是白鲸),我要逐字逐字而不是逐字逐字地走。因此某些单词的末尾可能会带有“,”,因此“ indignity”不会与“ indignity”对应。
KDecker 2014年


Lolx-您和我接受面试前的家庭锻炼一样吗?在Moby Dick中找到50个最常用的单词并报告其出现频率。我用C ++做到了,IIRC
Mawg说要恢复Monica

1
@Mawg这是我的本科生“云计算”课程中的一项练习。
KDecker

Answers:


127

使用 re.sub

import re

regex = re.compile('[^a-zA-Z]')
#First parameter is the replacement, second parameter is your input string
regex.sub('', 'ab3d*E')
#Out: 'abdE'

或者,如果您只想删除一组特定的字符(因为输入中可以使用撇号...)

regex = re.compile('[,\.!?]') #etc.

嗯,我可以很容易地找到它,但是删除所有非字母数字(空格除外)的模式又如何呢?
KDecker 2014年

1
只需在集合类中添加一个空格即可。即^a-zA-Z 不只是^a-zA-Z
limasxgoesto0 2014年

除非您还担心换行符,否则在这种情况下a-zA-Z \n。我正在尝试找到一个将两个都合而为一的正则表达式,但是使用\w还是\W没有给我所需的行为。\n在这种情况下,您可能只需要添加即可。
limasxgoesto0 2014年

啊,换行符。多数民众赞成在我的问题所在,我正在比较我的结果与给定的结果,但我仍然不参加。我认为那是我的问题!谢谢//嗯,我用换行符char尝试了相同的结果,我想还有一个我想念的.. //嗯……
KDecker 2014年

48

如果您不想使用正则表达式,可以尝试

''.join([i for i in s if i.isalpha()])

我该如何加入?与''.join?printing s仅获得一个过滤器对象
PirateApp '18

哇,这就是我一直在寻找的东西。这考虑到汉字,平假名,片假名等。荣誉
root163

34

您可以使用re.sub()函数删除以下字符:

>>> import re
>>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def")
'ABCabcdef'

re.sub(匹配模式,替换字符串,搜索字符串)

  • "[^a-zA-Z]+" -查找不是a-zA-z的任何字符组。
  • "" -将匹配的字符替换为“”

请注意,这也将删除重音字母:ãâàáéèçõ等
布拉德·阿伦斯

19

尝试:

s = ''.join(filter(str.isalnum, s))

这将从字符串中获取每个字符,仅保留字母数字字符,并从中返回一个字符串。


1
该答案可能会使用更多解释,并链接到相关文档。
pdoherty926

4

最快的方法是正则表达式

#Try with regex first
t0 = timeit.timeit("""
s = r2.sub('', st)

""", setup = """
import re
r2 = re.compile(r'[^a-zA-Z0-9]', re.MULTILINE)
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)

#Try with join method on filter
t0 = timeit.timeit("""
s = ''.join(filter(str.isalnum, st))

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""",
number = 1000000)
print(t0)

#Try with only join
t0 = timeit.timeit("""
s = ''.join(c for c in st if c.isalnum())

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)


2.6002226710006653 Method 1 Regex
5.739747313000407 Method 2 Filter + Join
6.540099570000166 Method 3 Join

0

如果您计划匹配特定的Unicode属性类,建议使用PyPiregex模块。该库还被证明更稳定,尤其是处理大文本时,并且在各种Python版本中都能产生一致的结果。您需要做的就是保持它为最新。

如果安装(使用pip intall regexpip3 install regex),则可以使用

import regex
print ( regex.sub(r'\P{L}+', '', 'ABCŁąć1-2!Абв3§4“5def”') )
// => ABCŁąćАбвdef

从中删除Unicode字母以外的所有1个或更多字符的块text。参见在线Python演示。您也可以使用"".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))来获得相同的结果。

在Python中re,为了匹配任何Unicode字母,可以使用该[^\W\d_]结构(匹配任何unicode字母?)。

因此,要删除所有非字母字符,可以匹配所有字母并加入结果:

result = "".join(re.findall(r'[^\W\d_]', text))

或者,删除与[^\W\d_]以下字符不匹配的所有字符:

result = re.sub(r'([^\W\d_])|.', r'\1', text, re.DOTALL)

在线观看正则表达式演示但是,由于Unicode标准正在发展,并且在不同的Python版本上可能会产生不一致的结果,并且与之匹配的字符集\w将取决于Python版本。regex强烈建议使用PyPi库以获得一致的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.