python cookbook 1數據結構和算法(4)

16過濾序列元素python

itertools.compress()app

最簡單的方式是用list表達式過濾
>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> [n for n in mylist if n > 0]
[1, 4, 10, 2, 3]
可是若是輸入量很大,最好用生成器
>>> pos = (n for n in mylist if n > 0)
>>> pos
<generator object <genexpr> at 0x7efdb34b6d20>
>>> for i in pos:
...     print i
... 
1
4
10
2
3
若是過濾準則比較複雜,最好用內建的filter方法
>>> values = ['1', '2', '-3', '-', '4', 'N/A', '5']
>>> def is_int(val):
...     try:
...        x=int(val)
...        return True
...     except ValueError:
...        return False
... 
>>> filter(is_int,values)
['1', '2', '-3', '4', '5']
另外一個比較實用的過濾器是itertools.compress(),須要一個迭代元素和一個對應的boolean序列做爲輸入
>>> from itertools import compress
>>> counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
>>> more5 = [n > 5 for n in counts]
>>> more5
[False, False, True, False, False, True, True, False]
>>> compress(counts,more5)
<itertools.compress object at 0x7efdb347c190>
compress返回的是一個迭代序列,須要用list()進行類型轉換
>>> list(compress(counts,more5))
[10, 7, 6]

17生成dict的子序列spa

prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}>>> p1 = { key:value for key, value in prices.items() if value > 200 }
>>> p1
{'AAPL': 612.78, 'IBM': 205.55}

18將name映射到序列元素
collections.namedtuple()是一個工廠方法,返回一個標準的tuple類型的子集,你須要提供類型名稱和應該有的域.prototype

>>> from collections import namedtuple
>>> Subscriber = namedtuple('Subscriberxx', ['addr', 'joined'])
程序中,'Subscriberxx'是類型名稱, ['addr', 'joined']是域 
>>> sub = Subscriber('jonesy@example.com', '2012-10-19')
>>> sub
Subscriberxx(addr='jonesy@example.com', joined='2012-10-19')
namedtuple()雖然像一個類實例,實際上確實和tuple交互支持經常使用的tuple操做,如索引和解包
>>> len(sub)
2
>>> addr, joined = sub
>>> addr
'jonesy@example.com'
>>> joined
'2012-10-19'

namedtuple()的一個重要用處是取代dict,dict須要更多的存儲空間,當須要建包含大量dict的數據時用namedtuple()更高效,但有一點須要注意,namedtuple()是不可變的,(tuple是不可變的) .code

若是須要改變,則使用_replace(),這會產生一個新的
>>> Stock = namedtuple('Stock', ['name', 'shares', 'price'])
>>> s = Stock('ACME', 100, 123.45)
>>> s.share=75
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Stock' object has no attribute 'share'
>>> s=s._replace(shares=75)
>>> s
Stock(name='ACME', shares=75, price=123.45)
咱們能夠利用_replace()建立一個包含默認值的原型
>>> Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
>>> stock_prototype = Stock('', 0, 0.0, None, None)
>>> def dict_to_stock(s):
...     return stock_prototype._replace(**s)
... 
>>> a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
>>> dict_to_stock(a)
Stock(name='ACME', shares=100, price=123.45, date=None, time=None)
>>> b = {'name': 'ACME', 'shares': 100, 'price': 123.45, 'date': '12/17/2012'}
>>> dict_to_stock(b)
Stock(name='ACME', shares=100, price=123.45, date='12/17/2012', time=None)
>>>

19同時轉換和歸併數據
orm

>>> nums = [1, 2, 3, 4, 5]
>>> s = sum((x * x for x in nums)) # 顯示的傳遞一個生成器表達式對象
>>> s = sum(x * x for x in nums)# 更加優雅的實現方式,省略了括號
>>> s
55
使用生成器是更優雅和高效的方式,應爲省去了建立一個臨時的tuple或list的損耗

20將多個映射合併爲一個
collections.ChainMap(僅python3適用)對象

>>> from collections import ChainMap
>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> c = ChainMap(a,b)
>>> c
ChainMap({'x': 1, 'z': 3}, {'z': 4, 'y': 2})
>>> c['x']
1
>>> c['y']
2
>>> c['z']
3
ChainMap只是把多個映射邏輯上組合在一塊兒,若是有多個相同的key,則取第一個
>>> len(c)
3
>>> list(c.keys())
['x', 'z', 'y']
>>> list(c.values())
[1, 3, 2]
對ChainMap的操做只會對第一個映射產生影響
>>> c['z']=10
>>> c['w']=3
>>> del c['x']
>>> c
ChainMap({'w': 3, 'z': 10}, {'z': 4, 'y': 2})
>>> a
{'w': 3, 'z': 10}
>>> del c['y']
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)
<ipython-input-5-df3e26fa6544> in <module>()
----> 1 del c['y']

/usr/lib/python3.4/collections/__init__.py in __delitem__(self, key)
    866             del self.maps[0][key]
    867         except KeyError:
--> 868             raise KeyError('Key not found in the first mapping: {!r}'.format(key))
    869 
    870     def popitem(self):

KeyError: "Key not found in the first mapping: 'y'"
---------------------------------------------------------------------------

ChainMap還能夠用new_child(),parents添加和刪除映射
>>> values=ChainMap()
>>> values['x']=1
>>> values=values.new_child()
>>> values['x']=2
>>> values=values.new_child()
>>> values['x']=3
>>> values
ChainMap({'x': 3}, {'x': 2}, {'x': 1})
>>> values['x']
3
>>> values=values.parents
>>> values
ChainMap({'x': 2}, {'x': 1})
>>> values['x']
2
有一種取代ChainMap的方式是用update()
>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>>b.update(a)
>>> b
{'x': 1, 'z': 3, 'y': 2}
>>> a
{'x': 1, 'z': 3}
>>> a['x']=13
>>> a
{'x': 13, 'z': 3}
>>> b
{'x': 1, 'z': 3, 'y': 2}
******************
這兩種方式有一個重要的區別,update原dict的改變不會影響到合併後的dict,但ChainMap會
******************
>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> merged = ChainMap(a, b)
>>> merged['x']
1
>>> a['x']=32
>>> merged['x']
32
相關文章
相關標籤/搜索