2007-06-15
Python Cook 1.10 从字符串中过滤非指定集合的字符
需求:
给定一个字符集合,需要构造一个过滤函数,使对于任意字符串s,改方法都能将其,使只包含集合内的字符.
讨论:
string的Translate方法是处理这一类问题的最快方法.然而,要想用translate解决需求提出的问题,我们需要做一些前期工作.translate的第一个参数是一个字符转换表.我们在这里并不需要转换字符 ,所以我们要让第一个参数表示不做任何转换.第二个参数是指要删除的字符串,因为我们的需求不是要删除字符,而是要保留字符,所以我们要构造出我们不需要的字符的集合.对于这样的要求,使用内函数是比较方便的,如在上一节,我们也实现了类似的需求.
在这一节中,我们首先分写了问题,将它划分为与处理和执行两个部分,这样不但减少了问题的复杂度,也提高了执行的效率.allchars是可重用的,可以被所有的过滤函数共享.而translate的第二个参数delete,我们使用了方法工厂来构造,也使用translate来达到最高的效率.
如果把allchars做为makefilter的参数,这样的过滤器能返回排序好的字符串,而且删除了重复字符.
可以这样来定义:
def canonicform(s):
return makefilter(s)(allchars)
其中return那一句,s做为makefilter的参数,而allchars做为thefilter的参数.
也可以使用lambda函数写法来定义内函数:
return lambda s: s.translate(allchars, delchars)
当然,使用def来定义使得代码更清晰,易读.
对于这个需求,我们也会想到用set来处理,然而,使用translate处理字符串是最高效的.当然其局限性也显而易见,它只能处理ascii常规字符,不能处理unicode.
为了使得unicode字符串也能满足我们的需求,还要做一些与处理工作,unicode的translate方法只有一个参数:一个map或者一个序列,它包含了字符串中字符的序列,表中不包含的字符,就直接复制到结果中去,对于要删除的字符,在map中对应的值是None.
一般来说,我们使用dict或list做为unicode字符串translate方法的参数.但对于这一节的需求(保留一些字符,删除其余的),我们要初始化一个巨大的map,然后把它们的值都映射为None.相反,我们构造一个简单的类,让它实现__getitem__方法.__getitem__方法是让外界可以通过[]来索引序列元素的方法,可以理解为重载了[].同时,对于简单类,我们可以使用别名来使用它.为了使类可以直接执行,我们让它实现恶劣__call__方法.
import sets
class Keeper(object):
def _ _init_ _(self, keep):
self.keep = sets.Set(map(ord, keep))
def _ _getitem_ _(self, n):
if n not in self.keep:
return None
return unichr(n)
def _ _call_ _(self, s):
return unicode(s).translate(self)
makefilter = Keeper
if _ _name_ _ == '_ _main_ _':
just_vowels = makefilter('aeiouy')
print just_vowels(u'four score and seven years ago')
# 输出: ouoeaeeyeaao
print just_vowels(u'tiger, tiger burning bright')
# 删除: ieieuii
相关说明:
translate(...)
S.translate(table) -> unicode
Return a copy of the string S, where all characters have been mapped
through the given translation table, which must be a mapping of
Unicode ordinals to Unicode ordinals, Unicode strings or None.
Unmapped characters are left untouched. Characters mapped to None
are deleted.
给定一个字符集合,需要构造一个过滤函数,使对于任意字符串s,改方法都能将其,使只包含集合内的字符.
讨论:
string的Translate方法是处理这一类问题的最快方法.然而,要想用translate解决需求提出的问题,我们需要做一些前期工作.translate的第一个参数是一个字符转换表.我们在这里并不需要转换字符 ,所以我们要让第一个参数表示不做任何转换.第二个参数是指要删除的字符串,因为我们的需求不是要删除字符,而是要保留字符,所以我们要构造出我们不需要的字符的集合.对于这样的要求,使用内函数是比较方便的,如在上一节,我们也实现了类似的需求.
import string理解这 一节的关键是理解string的maketrans和translate的实现机制.translate返回了一个字符串s的副本,在副本中,处于第一个参数(转换表)中的字符被替换了,而处于第二个参数中的字符被删除了.maketrans方法是用来构造字符转换表的.所谓字符转换表t是一个包含256个字符的字符串: 当你把t做为translate的第一个参数时,s中的每一个字符c都被转换为t[ord(c)].
# 构造一个字符转换表,表示不做任何转换.
allchars = string.maketrans('', '')
def makefilter(keep):
# 构造出我们不需要的字符集合
delchars = allchars.translate(allchars, keep)
# 定义内函数,返回我们需要的过滤器.
def thefilter(s):
return s.translate(allchars, delchars)
return thefilter
if _ _name_ _ == '_ _main_ _':
just_vowels = makefilter('aeiouy')
print just_vowels('four score and seven years ago')
# 输出: ouoeaeeyeaao
print just_vowels('tiger, tiger burning bright')
# 输出: ieieuii
在这一节中,我们首先分写了问题,将它划分为与处理和执行两个部分,这样不但减少了问题的复杂度,也提高了执行的效率.allchars是可重用的,可以被所有的过滤函数共享.而translate的第二个参数delete,我们使用了方法工厂来构造,也使用translate来达到最高的效率.
如果把allchars做为makefilter的参数,这样的过滤器能返回排序好的字符串,而且删除了重复字符.
可以这样来定义:
def canonicform(s):
return makefilter(s)(allchars)
其中return那一句,s做为makefilter的参数,而allchars做为thefilter的参数.
也可以使用lambda函数写法来定义内函数:
return lambda s: s.translate(allchars, delchars)
当然,使用def来定义使得代码更清晰,易读.
对于这个需求,我们也会想到用set来处理,然而,使用translate处理字符串是最高效的.当然其局限性也显而易见,它只能处理ascii常规字符,不能处理unicode.
为了使得unicode字符串也能满足我们的需求,还要做一些与处理工作,unicode的translate方法只有一个参数:一个map或者一个序列,它包含了字符串中字符的序列,表中不包含的字符,就直接复制到结果中去,对于要删除的字符,在map中对应的值是None.
一般来说,我们使用dict或list做为unicode字符串translate方法的参数.但对于这一节的需求(保留一些字符,删除其余的),我们要初始化一个巨大的map,然后把它们的值都映射为None.相反,我们构造一个简单的类,让它实现__getitem__方法.__getitem__方法是让外界可以通过[]来索引序列元素的方法,可以理解为重载了[].同时,对于简单类,我们可以使用别名来使用它.为了使类可以直接执行,我们让它实现恶劣__call__方法.
import sets
class Keeper(object):
def _ _init_ _(self, keep):
self.keep = sets.Set(map(ord, keep))
def _ _getitem_ _(self, n):
if n not in self.keep:
return None
return unichr(n)
def _ _call_ _(self, s):
return unicode(s).translate(self)
makefilter = Keeper
if _ _name_ _ == '_ _main_ _':
just_vowels = makefilter('aeiouy')
print just_vowels(u'four score and seven years ago')
# 输出: ouoeaeeyeaao
print just_vowels(u'tiger, tiger burning bright')
# 删除: ieieuii
相关说明:
translate(...)
S.translate(table) -> unicode
Return a copy of the string S, where all characters have been mapped
through the given translation table, which must be a mapping of
Unicode ordinals to Unicode ordinals, Unicode strings or None.
Unmapped characters are left untouched. Characters mapped to None
are deleted.
标签: Python