想象一个字符串,比如'Agh#$%#%2341- - !zdrkfd',我只希望对它进行一些操作,只返回小写字母(例如),在这种情况下会带上'ghzdrkfd'。
你是如何用Python做到的?显而易见的方法是创建一个字符列表,'a'到'z',然后迭代我的字符串中的字符,并逐个字符地构建一个新字符串。这看起来很原始。
我想知道正则表达式是否合适。替换不需要的字符似乎有问题,我倾向于将白名单优先于黑名单。 .match
函数似乎不合适。我查看了Python网站上的相应页面,但没有找到适合的方法。
如果正则表达式不合适并且正确的方法是循环,是否有一个简单的函数将字符串“爆炸”到列表中?或者我只是在那里打另一个循环?
答案 0 :(得分:32)
如果您正在寻找效率。使用translate功能是最快的。
它可用于快速替换字符和/或删除它们。
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
答案 1 :(得分:18)
s = 'Agh#$%#%2341- -!zdrkfd'
print ''.join(c for c in s if c.islower())
String对象是可迭代的;没有必要将字符串“爆炸”成列表。你可以在列表理解中放入你想要的任何条件,它会相应地过滤字符。
您也可以使用正则表达式实现此功能,但这只会隐藏循环。正则表达式库仍然必须遍历字符串的字符才能过滤它们。
答案 2 :(得分: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'
答案 3 :(得分:4)
s = 'ASDjifjASFJ7364'
s_lowercase = ''.join(filter(lambda c: c.islower(), s))
print s_lowercase #print 'jifj'
答案 4 :(得分:4)
>>> s = 'Agh#$%#%2341- -!zdrkfd'
>>> ''.join(i for i in s if i in 'qwertyuiopasdfghjklzxcvbnm')
'ghzdrkfd'
答案 5 :(得分:2)
采用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
调用将从输入字符串中删除那些并产生所需的结果。
答案 6 :(得分: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):
filter(function,iterable)
从iterable的那些元素构造一个列表,该函数返回true。 iterable可以是序列,支持迭代的容器,也可以是迭代器。如果iterable是字符串或元组,则结果也具有该类型;否则它总是一个列表。如果function为None,则假定为identity函数,即删除所有可迭代的false元素。
这是使用filter()的一种方式:
filtered_list = filter(lambda c: c.islower(), s)
答案 7 :(得分:0)
我会使用正则表达式。对于小写匹配[a-z]。
答案 8 :(得分:0)
import string
print "".join([c for c in "Agh#$%#%2341- -!zdrkfd" if c in string.lowercase])
答案 9 :(得分:0)
import string
print filter(string.lowercase.__contains__, "lowerUPPER")
print filter("123".__contains__, "a1b2c3")