這貨很強(qiáng)大, 必須掌握
文檔 鏈接 http://docs.python.org/2/library/itertools.html
pymotw 鏈接 http://pymotw.com/2/itertools/
基本是基于文檔的翻譯和補(bǔ)充,相當(dāng)于翻譯了
itertools用于高效循環(huán)的迭代函數(shù)集合
組成
總體,整體了解
無(wú)限迭代器
迭代器???????? 參數(shù)???????? 結(jié)果??????????????????????????????????????????????? 例子
count()???? start, [step]?? start, start+step, start+2*step, ...??????????????? count(10) --> 10 11 12 13 14 ...
cycle()???? p?????????????? p0, p1, ... plast, p0, p1, ...????????????????????? cycle('ABCD') --> A B C D A B C D ...
repeat()??? elem [,n]?????? elem, elem, elem, ... endlessly or up to n times??? repeat(10, 3) --> 10 10 10
處理輸入序列迭代器
迭代器????????? 參數(shù)??????????? 結(jié)果??????????????????????????????????????? 例子
chain()???? p, q, ...?????????? p0, p1, ... plast, q0, q1, ...????????????? chain('ABC', 'DEF') --> A B C D E F
compress()? data, selectors???? (d[0] if s[0]), (d[1] if s[1]), ...???????? compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
dropwhile() pred, seq?????????? seq[n], seq[n+1], starting when pred fails? dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
groupby()?? iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v)
ifilter()?? pred, seq?????????? elements of seq where pred(elem) is True??? ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9
ifilterfalse()? pred, seq?????? elements of seq where pred(elem) is False?? ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
islice()??? seq, [start,] stop [, step] elements from seq[start:stop:step]? islice('ABCDEFG', 2, None) --> C D E F G
imap()????? func, p, q, ...???? func(p0, q0), func(p1, q1), ...???????????? imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000
starmap()?? func, seq?????????? func(*seq[0]), func(*seq[1]), ...?????????? starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
tee()?????? it, n?????????????? it1, it2 , ... itn splits one iterator into n
takewhile() pred, seq?????????? seq[0], seq[1], until pred fails??????????? takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
izip()????? p, q, ...?????????? (p[0], q[0]), (p[1], q[1]), ...???????????? izip('ABCD', 'xy') --> Ax By
izip_longest()? p, q, ...?????? (p[0], q[0]), (p[1], q[1]), ...???????????? izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
組合生成器
迭代器????????? 參數(shù)??????????????????????? 結(jié)果
product()?????? p, q, ... [repeat=1]??????? cartesian product, equivalent to a nested for-loop
permutations()? p[, r]????????????????????? r-length tuples, all possible orderings, no repeated elements
combinations()? p, r??????????????????????? r-length tuples, in sorted order, no repeated elements
combinations_with_replacement() p, r??????? r-length tuples, in sorted order, with repeated elements
product('ABCD', repeat=2)?????????????????? AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
permutations('ABCD', 2)???????????????????? AB AC AD BA BC BD CA CB CD DA DB DC
combinations('ABCD', 2)???????????????????? AB AC AD BC BD CD
combinations_with_replacement('ABCD', 2)??? AA AB AC AD BB BC BD CC CD DD
第一部分
itertools.count(start=0, step=1)
創(chuàng)建一個(gè)迭代器,生成從n開(kāi)始的連續(xù)整數(shù),如果忽略n,則從0開(kāi)始計(jì)算(注意:此迭代器不支持長(zhǎng)整數(shù))
如果超出了sys.maxint,計(jì)數(shù)器將溢出并繼續(xù)從-sys.maxint-1開(kāi)始計(jì)算。
定義
def count(start=0, step=1):
??? # count(10) --> 10 11 12 13 14 ...
??? # count(2.5, 0.5) -> 2.5 3.0 3.5 ...
??? n = start
??? while True:
??????? yield n
??????? n += step
等同于(start + step * i for i in count())
使用
from itertools import *
for i in izip(count(1), ['a', 'b', 'c']):
??? print i
(1, 'a')
(2, 'b')
(3, 'c')
itertools.repeat(object[, times])
創(chuàng)建一個(gè)迭代器,重復(fù)生成object,times(如果已提供)指定重復(fù)計(jì)數(shù),如果未提供times,將無(wú)止盡返回該對(duì)象。
定義
def repeat(object, times=None):
??? # repeat(10, 3) --> 10 10 10
??? if times is None:
??????? while True:
??????????? yield object
??? else:
??????? for i in xrange(times):
??????????? yield object
使用
from itertools import *
for i in repeat('over-and-over', 5):
??? print i
over-and-over
over-and-over
over-and-over
over-and-over
over-and-over
第二部分
itertools.chain(*iterables)
將多個(gè)迭代器作為參數(shù), 但只返回單個(gè)迭代器, 它產(chǎn)生所有參數(shù)迭代器的內(nèi)容, 就好像他們是來(lái)自于一個(gè)單一的序列.
def chain(*iterables):
??? # chain('ABC', 'DEF') --> A B C D E F
??? for it in iterables:
??????? for element in it:
??????????? yield element
使用
from itertools import *
for i in chain([1, 2, 3], ['a', 'b', 'c']):
??? print i
1
2
3
a
b
c
from itertools import chain, imap
def flatmap(f, items):
??? return chain.from_iterable(imap(f, items))
>>> list(flatmap(os.listdir, dirs))
>>> ['settings.py', 'wsgi.py', 'templates', 'app.py',
???? 'templates', 'index.html, 'config.json']
itertools.compress(data, selectors)
提供一個(gè)選擇列表,對(duì)原始數(shù)據(jù)進(jìn)行篩選
def compress(data, selectors):
??? # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
??? return (d for d, s in izip(data, selectors) if s)
itertools.dropwhile(predicate, iterable)
創(chuàng)建一個(gè)迭代器,只要函數(shù)predicate(item)為T(mén)rue,就丟棄iterable中的項(xiàng),如果predicate返回False,就會(huì)生成iterable中的項(xiàng)和所有后續(xù)項(xiàng)。
即:在條件為false之后的第一次, 返回迭代器中剩下來(lái)的項(xiàng).
def dropwhile(predicate, iterable):
??? # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
??? iterable = iter(iterable)
??? for x in iterable:
??????? if not predicate(x):
??????????? yield x
??????????? break
??? for x in iterable:
??????? yield x
使用
from itertools import *
def should_drop(x):
??? print 'Testing:', x
??? return (x<1)
for i in dropwhile(should_drop, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
??? print 'Yielding:', i
Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Yielding: 2
Yielding: 3
Yielding: 4
Yielding: 1
Yielding: -2
itertools.groupby(iterable[, key])
返回一個(gè)產(chǎn)生按照key進(jìn)行分組后的值集合的迭代器.
如果iterable在多次連續(xù)迭代中生成了同一項(xiàng),則會(huì)定義一個(gè)組,如果將此函數(shù)應(yīng)用一個(gè)分類(lèi)列表,那么分組將定義該列表中的所有唯一項(xiàng),key(如果已提供)是一個(gè)函數(shù),應(yīng)用于每一項(xiàng),如果此函數(shù)存在返回值,該值將用于后續(xù)項(xiàng)而不是該項(xiàng)本身進(jìn)行比較,此函數(shù)返回的迭代器生成元素(key, group),其中key是分組的鍵值,group是迭代器,生成組成該組的所有項(xiàng)。
即:按照keyfunc函數(shù)對(duì)序列每個(gè)元素執(zhí)行后的結(jié)果分組(每個(gè)分組是一個(gè)迭代器), 返回這些分組的迭代器
等價(jià)于
class groupby(object):
??? # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
??? # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
??? def __init__(self, iterable, key=None):
??????? if key is None:
??????????? key = lambda x: x
??????? self.keyfunc = key
??????? self.it = iter(iterable)
??????? self.tgtkey = self.currkey = self.currvalue = object()
??? def __iter__(self):
??????? return self
??? def next(self):
??????? while self.currkey == self.tgtkey:
??????????? self.currvalue = next(self.it)??? # Exit on StopIteration
??????????? self.currkey = self.keyfunc(self.currvalue)
??????? self.tgtkey = self.currkey
??????? return (self.currkey, self._grouper(self.tgtkey))
??? def _grouper(self, tgtkey):
??????? while self.currkey == tgtkey:
??????????? yield self.currvalue
??????????? self.currvalue = next(self.it)??? # Exit on StopIteration
??????????? self.currkey = self.keyfunc(self.currvalue)
應(yīng)用
from itertools import groupby
qs = [{'date' : 1},{'date' : 2}]
[(name, list(group)) for name, group in itertools.groupby(qs, lambda p:p['date'])]
Out[77]: [(1, [{'date': 1}]), (2, [{'date': 2}])]
>>> from itertools import *
>>> a = ['aa', 'ab', 'abc', 'bcd', 'abcde']
>>> for i, k in groupby(a, len):
...???? print i, list(k)
...
2 ['aa', 'ab']
3 ['abc', 'bcd']
5 ['abcde']
另一個(gè)例子
from itertools import *
from operator import itemgetter
d = dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3)
di = sorted(d.iteritems(), key=itemgetter(1))
for k, g in groupby(di, key=itemgetter(1)):
??? print k, map(itemgetter(0), g)
1 ['a', 'c', 'e']
2 ['b', 'd', 'f']
3 ['g']
itertools.ifilter(predicate, iterable)
返回的是迭代器類(lèi)似于針對(duì)列表的內(nèi)置函數(shù) filter() , 它只包括當(dāng)測(cè)試函數(shù)返回true時(shí)的項(xiàng). 它不同于 dropwhile()
創(chuàng)建一個(gè)迭代器,僅生成iterable中predicate(item)為T(mén)rue的項(xiàng),如果predicate為None,將返回iterable中所有計(jì)算為T(mén)rue的項(xiàng)
對(duì)函數(shù)func執(zhí)行返回真的元素的迭代器
def ifilter(predicate, iterable):
??? # ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9
??? if predicate is None:
??????? predicate = bool
??? for x in iterable:
??????? if predicate(x):
??????????? yield x
使用
from itertools import *
def check_item(x):
??? print 'Testing:', x
??? return (x<1)
for i in ifilter(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
??? print 'Yielding:', i
Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Testing: 2
Testing: 3
Testing: 4
Testing: 1
Testing: -2
Yielding: -2
itertools.ifilterfalse(predicate, iterable)
和ifilter(函數(shù)相反 , 返回一個(gè)包含那些測(cè)試函數(shù)返回false的項(xiàng)的迭代器)
創(chuàng)建一個(gè)迭代器,僅生成iterable中predicate(item)為False的項(xiàng),如果predicate為None,則返回iterable中所有計(jì)算為False的項(xiàng) 對(duì)函數(shù)func執(zhí)行返回假的元素的迭代器
def ifilterfalse(predicate, iterable):
??? # ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
??? if predicate is None:
??????? predicate = bool
??? for x in iterable:
??????? if not predicate(x):
??????????? yield x
使用
from itertools import *
def check_item(x):
??? print 'Testing:', x
??? return (x<1)
for i in ifilterfalse(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
??? print 'Yielding:', i
Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Testing: 2
Yielding: 2
Testing: 3
Yielding: 3
Testing: 4
Yielding: 4
Testing: 1
Yielding: 1
Testing: -2
itertools.islice(iterable, stop)
itertools.islice(iterable, start, stop[, step])
返回的迭代器是返回了輸入迭代器根據(jù)索引來(lái)選取的項(xiàng)
創(chuàng)建一個(gè)迭代器,生成項(xiàng)的方式類(lèi)似于切片返回值: iterable[start : stop : step],將跳過(guò)前start個(gè)項(xiàng),迭代在stop所指定的位置停止,step指定用于跳過(guò)項(xiàng)的步幅。 與切片不同,負(fù)值不會(huì)用于任何start,stop和step, 如果省略了start,迭代將從0開(kāi)始,如果省略了step,步幅將采用1.
返回序列seq的從start開(kāi)始到stop結(jié)束的步長(zhǎng)為step的元素的迭代器
def islice(iterable, *args):
??? # islice('ABCDEFG', 2) --> A B
??? # islice('ABCDEFG', 2, 4) --> C D
??? # islice('ABCDEFG', 2, None) --> C D E F G
??? # islice('ABCDEFG', 0, None, 2) --> A C E G
??? s = slice(*args)
??? it = iter(xrange(s.start or 0, s.stop or sys.maxint, s.step or 1))
??? nexti = next(it)
??? for i, element in enumerate(iterable):
??????? if i == nexti:
??????????? yield element
??????????? nexti = next(it)
使用
from itertools import *
print 'Stop at 5:'
for i in islice(count(), 5):
??? print i
print 'Start at 5, Stop at 10:'
for i in islice(count(), 5, 10):
??? print i
print 'By tens to 100:'
for i in islice(count(), 0, 100, 10):
??? print i
Stop at 5:
0
1
2
3
4
Start at 5, Stop at 10:
5
6
7
8
9
By tens to 100:
0
10
20
30
40
50
60
70
80
90
itertools.imap(function, *iterables)
創(chuàng)建一個(gè)迭代器,生成項(xiàng)function(i1, i2, ..., iN),其中i1,i2...iN分別來(lái)自迭代器iter1,iter2 ... iterN,如果function為None,則返回(i1, i2, ..., iN)形式的元組,只要提供的一個(gè)迭代器不再生成值,迭代就會(huì)停止。
即:返回一個(gè)迭代器, 它是調(diào)用了一個(gè)其值在輸入迭代器上的函數(shù), 返回結(jié)果. 它類(lèi)似于內(nèi)置函數(shù) map() , 只是前者在任意輸入迭代器結(jié)束后就停止(而不是插入None值來(lái)補(bǔ)全所有的輸入).
返回序列每個(gè)元素被func執(zhí)行后返回值的序列的迭代器
def imap(function, *iterables):
??? # imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000
??? iterables = map(iter, iterables)
??? while True:
??????? args = [next(it) for it in iterables]
??????? if function is None:
??????????? yield tuple(args)
??????? else:
??????????? yield function(*args)
使用
from itertools import *
print 'Doubles:'
for i in imap(lambda x:2*x, xrange(5)):
??? print i
print 'Multiples:'
for i in imap(lambda x,y:(x, y, x*y), xrange(5), xrange(5,10)):
??? print '%d * %d = %d' % i
Doubles:
0
2
4
6
8
Multiples:
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36
itertools.starmap(function, iterable)
創(chuàng)建一個(gè)迭代器,生成值func(*item),其中item來(lái)自iterable,只有當(dāng)iterable生成的項(xiàng)適用于這種調(diào)用函數(shù)的方式時(shí),此函數(shù)才有效。
對(duì)序列seq的每個(gè)元素作為func的參數(shù)列表執(zhí)行, 返回執(zhí)行結(jié)果的迭代器
def starmap(function, iterable):
??? # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
??? for args in iterable:
??????? yield function(*args)
使用
from itertools import *
values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
for i in starmap(lambda x,y:(x, y, x*y), values):
??? print '%d * %d = %d' % i
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36
itertools.tee(iterable[, n=2])
返回一些基于單個(gè)原始輸入的獨(dú)立迭代器(默認(rèn)為2). 它和Unix上的tee工具有點(diǎn)語(yǔ)義相似, 也就是說(shuō)它們都重復(fù)讀取輸入設(shè)備中的值并將值寫(xiě)入到一個(gè)命名文件和標(biāo)準(zhǔn)輸出中
從iterable創(chuàng)建n個(gè)獨(dú)立的迭代器,創(chuàng)建的迭代器以n元組的形式返回,n的默認(rèn)值為2,此函數(shù)適用于任何可迭代的對(duì)象,但是,為了克隆原始迭代器,生成的項(xiàng)會(huì)被緩存,并在所有新創(chuàng)建的迭代器中使用,一定要注意,不要在調(diào)用tee()之后使用原始迭代器iterable,否則緩存機(jī)制可能無(wú)法正確工作。
把一個(gè)迭代器分為n個(gè)迭代器, 返回一個(gè)元組.默認(rèn)是兩個(gè)
def tee(iterable, n=2):
??? it = iter(iterable)
??? deques = [collections.deque() for i in range(n)]
??? def gen(mydeque):
??????? while True:
??????????? if not mydeque:???????????? # when the local deque is empty
??????????????? newval = next(it)?????? # fetch a new value and
??????????????? for d in deques:??????? # load it to all the deques
??????????????????? d.append(newval)
??????????? yield mydeque.popleft()
??? return tuple(gen(d) for d in deques)
使用
from itertools import *
r = islice(count(), 5)
i1, i2 = tee(r)
for i in i1:
??? print 'i1:', i
for i in i2:
??? print 'i2:', i
i1: 0
i1: 1
i1: 2
i1: 3
i1: 4
i2: 0
i2: 1
i2: 2
i2: 3
i2: 4
itertools.takewhile(predicate, iterable)
和dropwhile相反
創(chuàng)建一個(gè)迭代器,生成iterable中predicate(item)為T(mén)rue的項(xiàng),只要predicate計(jì)算為False,迭代就會(huì)立即停止。
即:從序列的頭開(kāi)始, 直到執(zhí)行函數(shù)func失敗.
def takewhile(predicate, iterable):
??? # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
??? for x in iterable:
??????? if predicate(x):
??????????? yield x
??????? else:
??????????? break
使用
from itertools import *
def should_take(x):
??? print 'Testing:', x
??? return (x<2)
for i in takewhile(should_take, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
??? print 'Yielding:', i
Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Yielding: 1
Testing: 2
itertools.izip(*iterables)
返回一個(gè)合并了多個(gè)迭代器為一個(gè)元組的迭代器. 它類(lèi)似于內(nèi)置函數(shù)zip(), 只是它返回的是一個(gè)迭代器而不是一個(gè)列表
創(chuàng)建一個(gè)迭代器,生成元組(i1, i2, ... iN),其中i1,i2 ... iN 分別來(lái)自迭代器iter1,iter2 ... iterN,只要提供的某個(gè)迭代器不再生成值,迭代就會(huì)停止,此函數(shù)生成的值與內(nèi)置的zip()函數(shù)相同。
izip(iter1, iter2, ... iterN):
返回:(it1[0],it2 [0], it3[0], ..), (it1[1], it2[1], it3[1], ..)...
def izip(*iterables):
??? # izip('ABCD', 'xy') --> Ax By
??? iterators = map(iter, iterables)
??? while iterators:
??????? yield tuple(map(next, iterators))
使用
from itertools import *
for i in izip([1, 2, 3], ['a', 'b', 'c']):
??? print i
(1, 'a')
(2, 'b')
(3, 'c')
itertools.izip_longest(*iterables[, fillvalue])
與izip()相同,但是迭代過(guò)程會(huì)持續(xù)到所有輸入迭代變量iter1,iter2等都耗盡為止,如果沒(méi)有使用fillvalue關(guān)鍵字參數(shù)指定不同的值,則使用None來(lái)填充已經(jīng)使用的迭代變量的值。
class ZipExhausted(Exception):
??? pass
def izip_longest(*args, **kwds):
??? # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
??? fillvalue = kwds.get('fillvalue')
??? counter = [len(args) - 1]
??? def sentinel():
??????? if not counter[0]:
??????????? raise ZipExhausted
??????? counter[0] -= 1
??????? yield fillvalue
??? fillers = repeat(fillvalue)
??? iterators = [chain(it, sentinel(), fillers) for it in args]
??? try:
??????? while iterators:
??????????? yield tuple(map(next, iterators))
??? except ZipExhausted:
??????? pass
第三部分
itertools.product(*iterables[, repeat])
笛卡爾積
創(chuàng)建一個(gè)迭代器,生成表示item1,item2等中的項(xiàng)目的笛卡爾積的元組,repeat是一個(gè)關(guān)鍵字參數(shù),指定重復(fù)生成序列的次數(shù)。
def product(*args, **kwds):
??? # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
??? # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
??? pools = map(tuple, args) * kwds.get('repeat', 1)
??? result = [[]]
??? for pool in pools:
??????? result = [x+[y] for x in result for y in pool]
??? for prod in result:
??????? yield tuple(prod)
例子
import itertools
a = (1, 2, 3)
b = ('A', 'B', 'C')
c = itertools.product(a,b)
for elem in c:
??? print elem
(1, 'A')
(1, 'B')
(1, 'C')
(2, 'A')
(2, 'B')
(2, 'C')
(3, 'A')
(3, 'B')
(3, 'C')
itertools.permutations(iterable[, r])
排列
創(chuàng)建一個(gè)迭代器,返回iterable中所有長(zhǎng)度為r的項(xiàng)目序列,如果省略了r,那么序列的長(zhǎng)度與iterable中的項(xiàng)目數(shù)量相同: 返回p中任意取r個(gè)元素做排列的元組的迭代器
def permutations(iterable, r=None):
??? # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
??? # permutations(range(3)) --> 012 021 102 120 201 210
??? pool = tuple(iterable)
??? n = len(pool)
??? r = n if r is None else r
??? if r > n:
??????? return
??? indices = range(n)
??? cycles = range(n, n-r, -1)
??? yield tuple(pool[i] for i in indices[:r])
??? while n:
??????? for i in reversed(range(r)):
??????????? cycles[i] -= 1
??????????? if cycles[i] == 0:
??????????????? indices[i:] = indices[i+1:] + indices[i:i+1]
??????????????? cycles[i] = n - i
??????????? else:
??????????????? j = cycles[i]
??????????????? indices[i], indices[-j] = indices[-j], indices[i]
??????????????? yield tuple(pool[i] for i in indices[:r])
??????????????? break
??????? else:
??????????? return
也可以用product實(shí)現(xiàn)
def permutations(iterable, r=None):
??? pool = tuple(iterable)
??? n = len(pool)
??? r = n if r is None else r
??? for indices in product(range(n), repeat=r):
??????? if len(set(indices)) == r:
??????????? yield tuple(pool[i] for i in indices)
itertools.combinations(iterable, r)
創(chuàng)建一個(gè)迭代器,返回iterable中所有長(zhǎng)度為r的子序列,返回的子序列中的項(xiàng)按輸入iterable中的順序排序 (不帶重復(fù))
def combinations(iterable, r):
??? # combinations('ABCD', 2) --> AB AC AD BC BD CD
??? # combinations(range(4), 3) --> 012 013 023 123
??? pool = tuple(iterable)
??? n = len(pool)
??? if r > n:
??????? return
??? indices = range(r)
??? yield tuple(pool[i] for i in indices)
??? while True:
??????? for i in reversed(range(r)):
??????????? if indices[i] != i + n - r:
??????????????? break
??????? else:
??????????? return
??????? indices[i] += 1
??????? for j in range(i+1, r):
??????????? indices[j] = indices[j-1] + 1
??????? yield tuple(pool[i] for i in indices)
#或者
def combinations(iterable, r):
??? pool = tuple(iterable)
??? n = len(pool)
??? for indices in permutations(range(n), r):
??????? if sorted(indices) == list(indices):
??????????? yield tuple(pool[i] for i in indices)
itertools.combinations_with_replacement(iterable, r)
創(chuàng)建一個(gè)迭代器,返回iterable中所有長(zhǎng)度為r的子序列,返回的子序列中的項(xiàng)按輸入iterable中的順序排序 (帶重復(fù))
def combinations_with_replacement(iterable, r):
??? # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
??? pool = tuple(iterable)
??? n = len(pool)
??? if not n and r:
??????? return
??? indices = [0] * r
??? yield tuple(pool[i] for i in indices)
??? while True:
??????? for i in reversed(range(r)):
??????????? if indices[i] != n - 1:
??????????????? break
??????? else:
??????????? return
??????? indices[i:] = [indices[i] + 1] * (r - i)
??????? yield tuple(pool[i] for i in indices)
或者
def combinations_with_replacement(iterable, r):
??? pool = tuple(iterable)
??? n = len(pool)
??? for indices in product(range(n), repeat=r):
??????? if sorted(indices) == list(indices):
??????????? yield tuple(pool[i] for i in indices)
第四部分
擴(kuò)展
使用現(xiàn)有擴(kuò)展功能
def take(n, iterable):
??? "Return first n items of the iterable as a list"
??? return list(islice(iterable, n))
def tabulate(function, start=0):
??? "Return function(0), function(1), ..."
??? return imap(function, count(start))
def consume(iterator, n):
??? "Advance the iterator n-steps ahead. If n is none, consume entirely."
??? # Use functions that consume iterators at C speed.
??? if n is None:
??????? # feed the entire iterator into a zero-length deque
??????? collections.deque(iterator, maxlen=0)
??? else:
??????? # advance to the empty slice starting at position n
??????? next(islice(iterator, n, n), None)
def nth(iterable, n, default=None):
??? "Returns the nth item or a default value"
??? return next(islice(iterable, n, None), default)
def quantify(iterable, pred=bool):
??? "Count how many times the predicate is true"
??? return sum(imap(pred, iterable))
def padnone(iterable):
??? """Returns the sequence elements and then returns None indefinitely.
??? Useful for emulating the behavior of the built-in map() function.
??? """
??? return chain(iterable, repeat(None))
def ncycles(iterable, n):
??? "Returns the sequence elements n times"
??? return chain.from_iterable(repeat(tuple(iterable), n))
def dotproduct(vec1, vec2):
??? return sum(imap(operator.mul, vec1, vec2))
def flatten(listOfLists):
??? "Flatten one level of nesting"
??? return chain.from_iterable(listOfLists)
def repeatfunc(func, times=None, *args):
??? """Repeat calls to func with specified arguments.
??? Example:? repeatfunc(random.random)
??? """
??? if times is None:
??????? return starmap(func, repeat(args))
??? return starmap(func, repeat(args, times))
def pairwise(iterable):
??? "s -> (s0,s1), (s1,s2), (s2, s3), ..."
??? a, b = tee(iterable)
??? next(b, None)
??? return izip(a, b)
def grouper(iterable, n, fillvalue=None):
??? "Collect data into fixed-length chunks or blocks"
??? # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
??? args = [iter(iterable)] * n
??? return izip_longest(fillvalue=fillvalue, *args)
def roundrobin(*iterables):
??? "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
??? # Recipe credited to George Sakkis
??? pending = len(iterables)
??? nexts = cycle(iter(it).next for it in iterables)
??? while pending:
??????? try:
??????????? for next in nexts:
??????????????? yield next()
??????? except StopIteration:
??????????? pending -= 1
??????????? nexts = cycle(islice(nexts, pending))
def powerset(iterable):
??? "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
??? s = list(iterable)
??? return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def unique_everseen(iterable, key=None):
??? "List unique elements, preserving order. Remember all elements ever seen."
??? # unique_everseen('AAAABBBCCDAABBB') --> A B C D
??? # unique_everseen('ABBCcAD', str.lower) --> A B C D
??? seen = set()
??? seen_add = seen.add
??? if key is None:
??????? for element in ifilterfalse(seen.__contains__, iterable):
??????????? seen_add(element)
??????????? yield element
??? else:
??????? for element in iterable:
??????????? k = key(element)
??????????? if k not in seen:
??????????????? seen_add(k)
??????????????? yield element
def unique_justseen(iterable, key=None):
??? "List unique elements, preserving order. Remember only the element just seen."
??? # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
??? # unique_justseen('ABBCcAD', str.lower) --> A B C A D
??? return imap(next, imap(itemgetter(1), groupby(iterable, key)))
def iter_except(func, exception, first=None):
??? """ Call a function repeatedly until an exception is raised.
??? Converts a call-until-exception interface to an iterator interface.
??? Like __builtin__.iter(func, sentinel) but uses an exception instead
??? of a sentinel to end the loop.
??? Examples:
??????? bsddbiter = iter_except(db.next, bsddb.error, db.first)
??????? heapiter = iter_except(functools.partial(heappop, h), IndexError)
??????? dictiter = iter_except(d.popitem, KeyError)
??????? dequeiter = iter_except(d.popleft, IndexError)
??????? queueiter = iter_except(q.get_nowait, Queue.Empty)
??????? setiter = iter_except(s.pop, KeyError)
??? """
??? try:
??????? if first is not None:
??????????? yield first()
??????? while 1:
??????????? yield func()
??? except exception:
??????? pass
def random_product(*args, **kwds):
??? "Random selection from itertools.product(*args, **kwds)"
??? pools = map(tuple, args) * kwds.get('repeat', 1)
??? return tuple(random.choice(pool) for pool in pools)
def random_permutation(iterable, r=None):
??? "Random selection from itertools.permutations(iterable, r)"
??? pool = tuple(iterable)
??? r = len(pool) if r is None else r
??? return tuple(random.sample(pool, r))
def random_combination(iterable, r):
??? "Random selection from itertools.combinations(iterable, r)"
??? pool = tuple(iterable)
??? n = len(pool)
??? indices = sorted(random.sample(xrange(n), r))
??? return tuple(pool[i] for i in indices)
def random_combination_with_replacement(iterable, r):
??? "Random selection from itertools.combinations_with_replacement(iterable, r)"
??? pool = tuple(iterable)
??? n = len(pool)
??? indices = sorted(random.randrange(n) for i in xrange(r))
??? return tuple(pool[i] for i in indices)
def tee_lookahead(t, i):
??? """Inspect the i-th upcomping value from a tee object
??? while leaving the tee object at its current position.
??? Raise an IndexError if the underlying iterator doesn't
??? have enough values.
??? """
??? for value in islice(t.__copy__(), i, None):
??????? return value
??? raise IndexError(i)
自定義擴(kuò)展
將序列按大小切分,更好的性能
from itertools import chain, islice
def chunks(iterable, size, format=iter):
??? it = iter(iterable)
??? while True:
??????? yield format(chain((it.next(),), islice(it, size - 1)))
>>> l = ["a", "b", "c", "d", "e", "f", "g"]
>>> for chunk in chunks(l, 3, tuple):...
??????? print chunk...
("a", "b", "c")
("d", "e", "f")
("g",)
補(bǔ)充
迭代工具,你最好的朋友
迭代工具模塊包含了操做指定的函數(shù)用于操作迭代器。想復(fù)制一個(gè)迭代器出來(lái)?鏈接兩個(gè)迭代器?以one liner(這里的one-liner只需一行代碼能搞定的任務(wù))用內(nèi)嵌的列表組合一組值?不使用list創(chuàng)建Map/Zip????,你要做的就是 import itertools,舉個(gè)例子吧:
四匹馬賽跑到達(dá)終點(diǎn)排名的所有可能性:
>>> horses = [1, 2, 3, 4]
>>> races = itertools.permutations(horses)
>>> print(races)
>>> print(list(itertools.permutations(horses)))
[(1, 2, 3, 4),
?(1, 2, 4, 3),
?(1, 3, 2, 4),
?(1, 3, 4, 2),
?(1, 4, 2, 3),
?(1, 4, 3, 2),
?(2, 1, 3, 4),
?(2, 1, 4, 3),
?(2, 3, 1, 4),
?(2, 3, 4, 1),
?(2, 4, 1, 3),
?(2, 4, 3, 1),
?(3, 1, 2, 4),
?(3, 1, 4, 2),
?(3, 2, 1, 4),
?(3, 2, 4, 1),
?(3, 4, 1, 2),
?(3, 4, 2, 1),
?(4, 1, 2, 3),
?(4, 1, 3, 2),
?(4, 2, 1, 3),
?(4, 2, 3, 1),
?(4, 3, 1, 2),
?(4, 3, 2, 1)]
理解迭代的內(nèi)部機(jī)制: 迭代(iteration)就是對(duì)可迭代對(duì)象(iterables,實(shí)現(xiàn)了__iter__()方法)和迭代器(iterators,實(shí)現(xiàn)了__next__()方法)的一個(gè)操作過(guò)程。可迭代對(duì)象是任何可返回一個(gè)迭代器的對(duì)象,迭代器是應(yīng)用在迭代對(duì)象中迭代的對(duì)象,換一種方式說(shuō)的話(huà)就是:iterable對(duì)象的__iter__()方法可以返回iterator對(duì)象,iterator通過(guò)調(diào)用next()方法獲取其中的每一個(gè)值(譯者注),讀者可以結(jié)合Java API中的 Iterable接口和Iterator接口進(jìn)行類(lèi)比。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
