python cookbook 读书笔记2(字符串处理2)

来源:互联网 发布:安装sass添加淘宝失败 编辑:程序博客网 时间:2024/06/04 22:47

1.8检查字符集中是否包含某字符集中的字符,在以下几个例子中,也就是检查seq是否包含aset中的项,各函数中Any结尾是部分包含,也就是只要有其中元素就返回true,All结尾的是全部包含,必须包含所有才返回true。(这里的例子都是字符集,也就是以单个字符为单位,与字符的顺序无关)。

一般的这么写

>>> def containAny(seq,aset):
...     for c in seq:
...             if c in aset:return Ture
...     return False
...
>>> a=['ee','etg4','g4g']
>>> b=['f3f','34f43']
>>> containAny(a,b)

False

使用迭代器代替for是更高级的方法,效率更高,但是代码易读性比较差,作者并不推荐,如下

>>> import itertools
>>> def cotainsAny2(seq,aset):
...     for item in itertools.ifilter(aset.__contains__,seq):
...             return True
...     return False
...
>>> cotainsAny2(a,b)
False

对于这个问题,作者更推荐的是使用集合的方法

>>> a=[1,2,3,4]
>>> b=[1,2,3,3]
>>> def containsAll(seq,aset):
...     return not set(aset).difference(seq)
...
>>> containsAll(a,b)
True
>>> containsAll(b,a)
False

而对于set的difference方法,是这样的

>>> set(a).difference(b)
set([4])
>>> set(b).difference(a)
set([])

相比于以上几种方式,作者更倾向于下一种方式,以下方式要调用两个字符串函数,这里先来介绍一下

① s.translate(table,str) 对字符串s移除str包含的字符,剩下的字符串按照table里的字符映射关系替换。table可以理解为转换表,比较'a' -> 'A', 'b'->'B'.

② tabel = string.maketrans('s1', 's2') s1 和 s2 的长度必须一致,maketrans生成一个转换表,若在s中有s1,则替换为s2,这个转换表是字符字符一个个对应的,没必要全部包含。(这里引自http://www.jb51.net/article/54404.htm)可以看一看。

>>> import string
>>> notrans=string.maketrans('','')#这里这么写是没有映射,保留原有的字符串。
>>> def containsAny(astr,strset):
...     return len(strset)!=len(strset.translate(notrans,astr))
...
>>> def containsAll(astr,street):
...     return not street.translate(notrans,astr)

>>> string1='asdfg'
>>> string2='asdfghjkl'
>>> string3='ferver'

>>> containsAny(string1,string2)
True
>>> containsAny(string2,string1)
True
>>> containsAny(string3,string1)
True
>>> containsAll(string3,string1)
False
>>> containsAll(string1,string2)
False
>>> containsAll(string2,string1)
True

1.9简化字符串translate方法的使用,作者在这里写了一个工厂函数,这个可以替换可以删除,个人觉得替换还是用replace好,本人才疏学浅,搞不懂python闭包,各位可以百度,这里给出函数。

>>> import string
>>> def translator(frm='',to='',delete='',keep=None):
...     if len(to)==1:
...             to=to*len(frm)
...     trans=string.maketrans(frm,to)
...     if keep is not None:
...             allchars=string.maketrans('','')
...             delete=allchars.translate(allchars,keep.translate(allchars,delete))
...     def translate(s):
...             return s.translate(trans,delete)
...     return translate
...

>>> digits_only=translator(keep=string.digits)
>>> digits_only('hello world:123456')
'123456'
>>> no_digits=translator(delete=string.digits)
>>> no_digits('hello world:123456')
'hello world:'
>>> replace_digits=translator(from=string.digits,to='*')
  File "<stdin>", line 1
    replace_digits=translator(from=string.digits,to='*')
                                 ^
SyntaxError: invalid syntax
>>> replace_digits=translator(frm=string.digits,to='*')
>>> replace_digits('hello world:123456')
'hello world:******'

1.10过滤字符串中不属于指定集合的字符,本节作者还是使用了string下的translate方法,只是将translate又一次封装,使他更加易用。

>>> import string
>>> allchars=string.maketrans('','')
>>> def makefilter(keep):
...     delchars=allchars.translate(allchars,keep)
...     def thefilter(s):
...             return s.translate(allchars,delchars)
...     return thefilter
...
>>> my_filter=makefilter('abc')

>>> my_filter('agenrgbtgcandnbnnnccccb')
'abcabccccb'

上面的写法对unicode字符串是无效的,鉴于对unicode字符串的问题,作者使用如下方式解决。

>>> 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
>>> myfilter=makefilter('abc')
>>> myfilter(u'wfwbwrgwecwrfbwfwcrgfbwrcfbcb')
u'bcbcbcbcb'

0 0
原创粉丝点击