22

想象一个字符串,比如 'Agh#$%#%2341- -!zdrkfd',我只想对其执行一些操作,以便只返回小写字母(例如),在这种情况下会带来 'ghzdrkfd '。

你如何在 Python 中做到这一点?显而易见的方法是创建一个字符列表,从“a”到“z”,然后遍历我的字符串中的字符,并仅在我的列表中逐个字符地构建一个新字符串。这看起来很原始。

我想知道正则表达式是否合适。替换不需要的字符似乎有问题,我倾向于将白名单列入黑名单。该.match功能似乎不合适。我查看了 Python 站点上的相应页面,但没有找到合适的方法。

如果正则表达式不合适并且正确的方法是循环,是否有一个简单的函数可以将字符串“分解”成列表?或者我只是在那里打另一个 for 循环?

4

10 回答 10

32

如果您正在寻找效率。使用翻译功能是最快的。

它可用于快速替换字符和/或删除它们。

import string
delete_table  = string.maketrans(
    string.ascii_lowercase, ' ' * len(string.ascii_lowercase)
)
table = string.maketrans('', '')

"Agh#$%#%2341- -!zdrkfd".translate(table, delete_table)

在 python 2.6 中:你不再需要第二张表了

import string
delete_table  = string.maketrans(
    string.ascii_lowercase, ' ' * len(string.ascii_lowercase)
)
"Agh#$%#%2341- -!zdrkfd".translate(None, delete_table)

这种方法比任何其他方法都快。当然,您需要将 delete_table 存储在某处并使用它。但即使你不存储它并每次都构建它,它仍然会比迄今为止其他建议的方法更快。

为了确认我的说法,这里是结果:

for i in xrange(10000):
    ''.join(c for c in s if c.islower())

real    0m0.189s
user    0m0.176s
sys 0m0.012s

在运行正则表达式解决方案时:

for i in xrange(10000):
    re.sub(r'[^a-z]', '', s)

real    0m0.172s
user    0m0.164s
sys 0m0.004s

[根据要求]如果您预编译正则表达式:

r = re.compile(r'[^a-z]')
for i in xrange(10000):
    r.sub('', s)

real    0m0.166s
user    0m0.144s
sys 0m0.008s

运行 translate 方法的次数相同:

real    0m0.075s
user    0m0.064s
sys 0m0.012s
于 2009-05-15T20:35:58.343 回答
18
s = 'Agh#$%#%2341- -!zdrkfd'  
print ''.join(c for c in s if c.islower())

字符串对象是可迭代的;无需将字符串“分解”成列表。您可以在列表推导中放置您想要的任何条件,它会相应地过滤字符。

您也可以使用正则表达式来实现这一点,但这只会隐藏循环。正则表达式库仍然需要遍历字符串的字符才能过滤它们。

于 2009-05-15T19:53:36.963 回答
5

使用正则表达式很容易,尤其是对于这种情况:

>>> import re
>>> s = 'ASDjifjASFJ7364'
>>> re.sub(r'[^a-z]+', '', s)
'jifj'

如果您打算多次这样做,最好事先编译正则表达式:

>>> import re
>>> s = 'ASDjifjASFJ7364'
>>> r = re.compile(r'[^a-z]+')
>>> r.sub('', s)
'jifj'
于 2009-05-15T19:58:27.373 回答
4
s = 'ASDjifjASFJ7364'
s_lowercase = ''.join(filter(lambda c: c.islower(), s))
print s_lowercase #print 'jifj'
于 2009-05-15T19:53:32.500 回答
4
>>> s = 'Agh#$%#%2341- -!zdrkfd'
>>> ''.join(i for i in s if  i in 'qwertyuiopasdfghjklzxcvbnm')
'ghzdrkfd'
于 2009-05-15T19:57:34.987 回答
2

一种更通用且更易于理解的解决方案,可以根据 a字符inputstring对其进行过滤:whitelist

inputstring = "Agh#$%#%2341- -!zdrkfd"
whitelist = "abcdefghijklmnopqrstuvwxyz"
remove = inputstring.translate(None, whitelist)
result = inputstring.translate(None, remove)
print result

这打印

ghzdrkfd

第一个string.translate从输入字符串中删除白名单中的所有字符。这给了我们想要删除的字符。第二个string.translate调用从输入字符串中删除那些并产生所需的结果。

于 2017-03-19T19:26:51.527 回答
1

如果您对处理字符串特别感兴趣,这是一种解决方案:

 s = 'Agh#$%#%2341- -!zdrkfd'
 lowercase_chars = [chr(i) for i in xrange(ord('a'), ord('z') + 1)]
 whitelist = set(lowercase_chars)
 filtered_list = [c for c in s if c in whitelist]

白名单实际上是为了提高效率而设置的(不是列表)。

如果需要字符串,请使用 join():

filtered_str = ''.join(filtered_list)

filter() 是一个更通用的解决方案。从文档(http://docs.python.org/library/functions.html):

过滤器(函数,可迭代)

从函数返回 true 的那些可迭代元素构造一个列表。iterable 可以是序列、支持迭代的容器或迭代器。如果 iterable 是字符串或元组,则结果也具有该类型;否则它总是一个列表。如果 function 为 None,则假定恒等函数,即移除 iterable 中所有为 false 的元素。

这将是使用 filter() 的一种方式:

filtered_list = filter(lambda c: c.islower(), s)
于 2009-05-15T20:59:53.403 回答
0

我会使用正则表达式。对于小写匹配 [az]。

于 2009-05-15T19:54:27.443 回答
0
import string
print "".join([c for c in "Agh#$%#%2341- -!zdrkfd" if c in string.lowercase])
于 2009-05-15T20:04:29.993 回答
0
import string

print filter(string.lowercase.__contains__, "lowerUPPER")
print filter("123".__contains__, "a1b2c3")
于 2015-04-28T16:54:47.237 回答