Python 如何过滤字符串,以便只返回列表中的字符?

Python 如何过滤字符串,以便只返回列表中的字符?,python,filter,whitelist,Python,Filter,Whitelist,想象一个字符串,如“Agh#$%#%2341---!我只希望对它执行一些操作,以便只返回小写字母(作为一个示例),在本例中,这将带来“ghzdrkfd” 如何在Python中实现这一点?显而易见的方法是创建一个由字符“a”到“z”组成的列表,然后迭代我的字符串中的字符,并逐个字符地构建一个新的字符串,只包含我列表中的字符。这似乎很原始 我想知道正则表达式是否合适。替换不需要的字符似乎有问题,我倾向于选择白名单而不是黑名单。.match功能似乎不合适。我已经在Python站点上查看了相应的页面,但

想象一个字符串,如“Agh#$%#%2341---!我只希望对它执行一些操作,以便只返回小写字母(作为一个示例),在本例中,这将带来“ghzdrkfd”

如何在Python中实现这一点?显而易见的方法是创建一个由字符“a”到“z”组成的列表,然后迭代我的字符串中的字符,并逐个字符地构建一个新的字符串,只包含我列表中的字符。这似乎很原始

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

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

s = 'ASDjifjASFJ7364'
s_lowercase = ''.join(filter(lambda c: c.islower(), s))
print s_lowercase #print 'jifj'
字符串对象是可编辑的;不需要将字符串“分解”为列表。您可以在列表中放入任何需要的条件,它将相应地过滤字符


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

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

使用正则表达式非常简单,尤其是在这种情况下:

>>> s = 'Agh#$%#%2341- -!zdrkfd'
>>> ''.join(i for i in s if  i in 'qwertyuiopasdfghjklzxcvbnm')
'ghzdrkfd'
>>> 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'

如果你在寻找效率。使用该函数是您可以获得的最快速度

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

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_表存储在某个位置并使用它。但即使您不每次都存储和构建它,它仍然会比目前推荐的其他方法更快

为了证实我的说法,以下是结果:

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

如果您对字符串特别感兴趣,这里有一个解决方案:

 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():


filter()是一种更通用的解决方案。从文档()中:

过滤器(功能,可调)

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

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


一种更通用、更易理解的解决方案,用于获取
输入字符串
,并根据
白名单
中的字符对其进行过滤:

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

ghzdrkfd

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

isalpha()是不需要的,因为非字母字符将在islower()上返回false。这也可以通过将
c.islower()
更改为例如“abcDEF”中的
c来修改为使用自定义字符列表
。该死——我以为我有更好的答案,但这更简单。结合本·布兰克的评论,使得答案相当笼统。我想我必须先列出我的名单,但一点也不需要。没有必要在s上列出电话名单。字符串对象是可编辑的。公平地说,你应该在循环之外编译正则表达式。我正在比较最建议的解决方案。Paolo Bergantino就是这样写他的表达式的。我把它作为一个一次性的解决方案写的,它显然是最好编译的,所以你应该这样比较它。为了公平起见,把正则表达式改为“[^a-z]+”。这样,它将一次性替换一系列匹配项,而不是一次替换一个字符。@gnud,我试过了,速度稍微快一点,但无法翻译匹配项。顺便说一句,字符串越大,translate和其他方法之间的性能差异就越大。在translate中,处理时间几乎不会随着字符串长度的增加而增加。公平地说,我在您的预编译版本上再次运行了测试,测试速度仍然比translate慢。正则表达式应该是“[^a-z]+”—这将显著提高性能。@gnud,您关于提高性能的看法是正确的。但它仍然比翻译慢得多。
filtered_str = ''.join(filtered_list)
filtered_list = filter(lambda c: c.islower(), s)
import string

print filter(string.lowercase.__contains__, "lowerUPPER")
print filter("123".__contains__, "a1b2c3")
inputstring = "Agh#$%#%2341- -!zdrkfd"
whitelist = "abcdefghijklmnopqrstuvwxyz"
remove = inputstring.translate(None, whitelist)
result = inputstring.translate(None, remove)
print result
ghzdrkfd