python自帶效能強悍的標準庫 itertools

金色旭光發表於2021-12-12

可迭代物件就像密閉容器裡的水,有貨倒不出

itertools是python內建的標準模組,提供了很多簡潔又高效的專用功能,使用得當能夠極大的簡化程式碼行數,同時所有方法都是實現了生成器函式,這就意味著極大的節省記憶體。
itertools提供的功能主要分為三大塊,以最新版本的3.10為例:

  1. 對可迭代物件無限迭代,無限輸出
  2. 對可迭代物件有限迭代
  3. 對可迭代物件排列組合

方法如下:

匯入包

>>> from iteratortools import *

無限迭代

iteratortools.count(start=0, step=1)

數值生成器,可以指定起始位置和步長,並且步長可以為浮點數。無限輸出,一直累加,在例子中需要邊睡眠1s邊輸出。

>>> import time
>>> iterator = count(4, 0.5)
>>> for i in iterator:
...     print(i)
...     time.sleep(1)
...
4
4.5
5.0
5.5
6.0
6.5
7.0
7.5

iteratortools.cycle(iteratorable)
無限迴圈取出可迭代物件裡的元素

>>> a = cycle("ABCD")
>>> import time
>>> for i in a:
...     print(i)
...     time.sleep(1)
...
A
B
C
D
A
B
C
D

iteratortools.repeat(object[, times])
不斷重複輸出整個object,如果指定了重複次數,則輸出指定次數,否則將無限重複。

>>> iterator = repeat('hello world', 10)
>>>
>>> for i in iterator:
...     print(i)
...
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
有了這個神器,對輸出10次hello world這種問題又有一種新解法

有限迭代

iteratortools.accumulate(iteratorable[, func, *, initial=None])
返回對列表中元素逐項的操作,操作有:

  1. 累加,返回累加到每一項的列表
  2. 累乘,返回累乘到每一項的列表
  3. 最小值,返回到當前項的最小值
  4. 最大值,返回到當前項的最大值
>>> [2, 4, 8, 1, 3, 5]
[2, 4, 8, 1, 3, 5]
>>> arr = [2, 4, 8, 1, 3, 5]
>>>
>>> add = accumulate(arr)
>>>
>>> list(add)
[2, 6, 14, 15, 18, 23]
>>>
>>> max = accumulate(arr, max)
>>> list(max)
[2, 4, 8, 8, 8, 8]
>>>
>>> import operator
>>> mul = accumulate(arr, operator.mul)
>>> list(mul)
[2, 8, 64, 64, 192, 960]
>>>
>>> min = accumulate(arr, min)
>>> list(min)
[2, 2, 2, 1, 1, 1]

iteratortools.chain(*iteratorables)
將多個可迭代物件構建成一個新的可迭代物件,統一返回。類似於將多個物件鏈成一條串

>>> iterator = chain([1,2,3],['a','b','c'],(5,6,7))
>>> list(iterator)
[1, 2, 3, 'a', 'b', 'c', 5, 6, 7]

優點:可以將多個可迭代物件整合成一個,避免逐個取值

chain.from_iteratorable(iteratorable)
將一個迭代物件中將所有元素類似於chain一樣,統一返回。

>>> chain.from_iteratorable(['abc','def'])
<iteratortools.chain object at 0x1083ae460>
>>> iterator = chain.from_iteratorable(['abc','def'])
>>> list(iterator)
['a', 'b', 'c', 'd', 'e', 'f']

iteratortools.compress(data, selectors)
按照真值表篩選元素

>>> arr = [1,2,3,4]
>>> selectors = [1,0,1,0]
>>>
>>> iterator = compress(arr, selectors)
>>>
>>> list(iterator)
[1, 3]

iteratortools.dropwhile(predicate, iteratorable)
按照條件篩選,丟棄掉第一次不符合條件時之前的所有元素

>>> arr = [1,2,3,2,1,2,1]
>>> iterator = dropwhile(lambda x: x<3, arr)
>>> list(iterator)
[3, 2, 1, 2, 1]

iteratortools.takewhile(predicate, iteratorable)
根據predicate條件篩選可迭代物件中的元素,只要元素為真就返回,第一次遇到不符合的條件就退出。
按照條件篩選,丟棄第一次遇到不符合條件之後的元素。行為類似於上一個dropwhile,區別在於丟棄的選擇不同。

iteratortools.filterfalse(predicate, iteratorable)
保留不符合條件的元素,返回迭代器

>>> arr = [1,2,3,4,5]
>>> iterator = filterfalse(lambda x:x<3, arr)
>>> list(iterator)
[3, 4, 5]

iteratortools.groupby(iteratorable, key=None)
按照指定的條件分類。輸出條件和符合條件的元素

>>> iterator = groupby(arr, lambda x: x>3)
>>> for condition ,numbers in iterator:
...     print(condition, list(numbers))
...
False [1, 2, 3]
True [4, 5]

iteratortools.islice(iteratorable, start, stop[, step])
對迭代器進行切片,老版本中不能指定start和stop以及步長,新版本可以。

>>> iterator = count()
>>> slice_iterator = islice(iterator, 10, 20, 2)
>>> list(slice_iterator)
[10, 12, 14, 16, 18]

iteratortools.starmap(function, iteratorable)
將function作用於可迭代物件上,類似於map函式

iteratortools.tee(iteratorable, n=2)
從一個可迭代物件中返回 n 個獨立的迭代器

>>> iterator = tee(arr)
>>> for i in iterator:
...     print(type(i), list(i))
...
<class 'iteratortools._tee'> [1, 2, 3, 4, 5]
<class 'iteratortools._tee'> [1, 2, 3, 4, 5]

iteratortools.zip_longest(*iteratorables, fillvalue=None)
建立一個迭代器,從每個可迭代物件中收集元素。如果可迭代物件的長度未對齊,將根據 fillvalue 填充缺失值。
迭代持續到耗光最長的可迭代物件。大致相當於:

>>> iterator = zip_longest("ABCD", "xy", fillvalue="-")
>>> list(iterator)
[('A', 'x'), ('B', 'y'), ('C', '-'), ('D', '-')]

排列組合迭代

iteratortools.product(*iteratorables, repeat=1)
生成多個可迭代物件的笛卡爾積
大致相當於生成器表示式中的巢狀迴圈。例如, product(A, B) 和 ((x,y) for x in A for y in B) 返回結果一樣。

>>> iterator = product("123", "abc")
>>> list(iterator)
[('1', 'a'), ('1', 'b'), ('1', 'c'), ('2', 'a'), ('2', 'b'), ('2', 'c'), ('3', 'a'), ('3', 'b'), ('3', 'c')]

將可選引數 repeat 設定為要重複的次數。例如,product(A, repeat=4) 和 product(A, A, A, A) 是一樣的

iteratortools.permutations(iteratorable, r=None)
由 iteratorable 元素生成長度為 r 的排列。元素的排列,類似於給一個[1,2,3],選取其中兩個元素,一共有多少種組合方法?不要求元素排列之後的位置。

>>> iter = permutations([1,2,3], r=3)
>>> list(iterator)
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

這個方法能夠完美解決演算法中的全排列問題,簡直是量身定做。如果早知道這麼簡單,當年考演算法也不會。。,哎
可參見leetcode46題:https://leetcode-cn.com/problems/permutations/

iteratortools.combinations(iteratorable, r)
返回由輸入 iteratorable 中元素組成長度為 r 的子序列。元素不可重複使用。子序列是要求元素在排列之後和之前的相對位置不變的。1,2,3中3在1的後面,子序列中3也一定在1的後面。

>>> iterator = combinations([1,2,3,4], r = 3)
>>> list(iterator)
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
>>> iterator = combinations([1], r = 3)
>>> list(iterator)
[]

這個方法可以曲線解決組合總數問題
https://leetcode-cn.com/problems/combination-sum/

iteratortools.combinations_with_replacement(iteratorable, r)
返回由輸入 iteratorable 中元素組成的長度為 r 的子序列,允許每個元素可重複出現

>>> iter = combinations_with_replacement([1,2,3,4], r=2)
>>> list(iter)
[(1, 1), (1, 2), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 3), (3, 4), (4, 4)]

>>> iterator = combinations_with_replacement([1], r=3)
>>> list(iterator)
[(1, 1, 1)]

相關文章