Python,从字符串中删除所有非字母字符
Posted
技术标签:
【中文标题】Python,从字符串中删除所有非字母字符【英文标题】:Python, remove all non-alphabet chars from string 【发布时间】:2014-04-26 14:06:01 【问题描述】:我正在编写一个 python MapReduce 字数统计程序。问题是数据中散布着许多非字母字符,我发现这篇文章Stripping everything but alphanumeric chars from a string in 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”对应。
Stripping everything but alphanumeric chars from a string in Python的可能重复
Lolx - 你有和我一样的面试前家庭练习吗?在 Moby Dick 中找到 50 个最常用的词并报告它们的频率。我是用 C++ 做的,IIRC
@Mawg 这是我本科“云计算”课上的一个练习。
【参考方案1】:
如果您计划匹配特定的 Unicode 属性类,建议使用 PyPi regex
module。这个库也被证明更稳定,尤其是处理大文本,并且在各种 Python 版本中产生一致的结果。您需要做的就是使其保持最新状态。
如果你安装它(使用pip install regex
或pip3 install regex
),你可以使用
import regex
print ( regex.sub(r'\PL+', '', 'ABCŁąć1-2!Абв3§4“5def”') )
// => ABCŁąćАбвdef
从text
中删除所有包含 1 个或多个字符的块,而不是 Unicode 字母。请参阅online Python demo。您也可以使用"".join(regex.findall(r'\pL+', 'ABCŁąć1-2!Абв3§4“5def”'))
来获得相同的结果。
在 Python re
中,为了匹配任何 Unicode 字母,可以使用 [^\W\d_]
构造 (Match any unicode letter?)。
因此,要删除所有非字母字符,您可以匹配所有字母并加入结果:
result = "".join(re.findall(r'[^\W\d_]', text))
或者,删除与[\W\d_]
模式匹配的所有字符(与[^\W\d_]
相反):
result = re.sub(r'[\W\d_]+', '', text)
请参阅regex demo online。 但是,由于 Unicode 标准在不断发展,您可能会在不同的 Python 版本中得到不一致的结果,并且与 \w
匹配的字符集将取决于 Python 版本。强烈建议使用 PyPi regex
库以获得一致的结果。
【讨论】:
【参考方案2】:试试:
s = ''.join(filter(str.isalnum, s))
这将从字符串中取出每个字符,只保留字母数字字符并从它们构建一个字符串。
【讨论】:
这很好,因为它可以处理像Å Å Ö这样的奇怪字符【参考方案3】:使用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.
【讨论】:
嗯,我可以很好地找到它,但是删除所有非字母数字(不包括空格)的模式呢? 只需在您的收藏类中添加一个空格。即^a-zA-Z
而不仅仅是^a-zA-Z
除非你也担心换行,在这种情况下a-zA-Z \n
。我试图找到一个将两者合二为一的正则表达式,但使用 \w
或 \W
并没有给我想要的行为。如果是这种情况,您可能只需要添加 \n
。
啊,换行符。那就是我的问题所在,我正在将我的结果与给定的结果进行比较,但我仍然没有。我想这是我的问题!谢谢 // 嗯,我用换行符尝试了相同的结果,我想还有一个我错过了.. // Duhhh... 大写和小写... // 感谢所有的帮助,现在完美! 【参考方案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
【讨论】:
【参考方案5】:如果你不想使用正则表达式,你可以试试
''.join([i for i in s if i.isalpha()])
【讨论】:
如何加入?与 ''.join ?打印 s 只得到一个过滤器对象 哇,这就是我想要的。这考虑了汉字、平假名、片假名等。荣誉【参考方案6】:您可以使用 re.sub() 函数删除这些字符:
>>> import re
>>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def")
'ABCabcdef'
re.sub(匹配模式,替换字符串,要搜索的字符串)
"[^a-zA-Z]+"
- 寻找任何不是的字符组
a-zA-z。
""
- 用“”替换匹配的字符
【讨论】:
请注意,这也会删除重音字母:ãâàéèçõ 等以上是关于Python,从字符串中删除所有非字母字符的主要内容,如果未能解决你的问题,请参考以下文章