Python-标准库之迭代器-itertools

  • Infinite iterators:  无穷迭代器   

count(start=0, step=1) --> start, start+step, start+2*step, ...   -->返回从1开始的无限个自然数序列,

# res = itertools.count(1)
# for n in res:
#     print(n)       #不敢执行

#解决方案:takewhile():与无穷迭代器连用,生成符合条件的序列
res = itertools.count(1)
fn = itertools.takewhile(lambda x: x <= 10, res)    #返回小于等于10的自然数序列
print(list(fn))
#执行结果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


cycle(p) --> p0, p1, ... plast, p0, p1, ...                      -->把传入的序列无限循环

res = itertools.cycle('ABC')
# for i in res:
#     print(i)      #不敢执行

#执行结果:A B C A B C


repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times   -->把一个元素无限重复,提供第二个参数可以限制重复次数

res = itertools.repeat('A',5)
for i in res:
    print(i,end=',',flush=True)
#执行结果:A,A,A,A,A
  • Iterators terminating on the shortest input sequence:     -->根据最短输入序列长度停止的迭代器

accumulate(p[, func]) --> p0, p0+p1, p0+p1+p2             -->返回累积汇总值(即后面的数等于前面的数的累加结果值)

#accumulate(iterable, func=operator.add, *, initial=None):返回累积汇总值(即后面的数等于前面的数的累加结果值)或其他给定函数的累积结果值,如果提供initial,即从初始值开始
#与functools.reduce()区别在于reduce只返回最终累积值

res = itertools.accumulate([1, 2, 3, 4, 5, 6, 6, 7, 8, 9 ,10])
print(list(res))
#执行结果: [1, 3, 6, 10, 15, 21, 27, 34, 42, 51, 61]

res = itertools.accumulate([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], func=operator.mul)  #累积乘积
print(list(res))
#执行结果: [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

res = itertools.accumulate([1, 2, 3, 4, 5, 6, 6, 7, 8, 9 ,10], initial=5)  #从5开始加1,加2....
print(list(res))
#执行结果: [5, 6, 8, 11, 15, 20, 26, 32, 39, 47, 56, 66]


chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...  :   -->p ,q为可迭代对象,将两个或几个可迭代对象中所有的元素合并

res = itertools.chain('abc','def')
for i in res:
    print(i, end=',', flush=True)
#执行结果: a,b,c,d,e,f
res = itertools.chain([1, 2, 3], [4, 5, 6])
for i in res:
    print(f"两个列表分别拆分并组合的结果为: {i}")
#执行结果为: 1 2 3 4 5 6


chain.from_iterable([p, q, ...]) --> p0, p1, ... plast, q0, q1, ...  -->将一个可迭代对象内部迭代,返回这个可迭代对象中所有的元素

#chain.from_iterable(iterable): 将一个可迭代对象内部迭代,返回这个可迭代对象中所有的元素
res = itertools.chain.from_iterable(["ABC", "DEF"])
for i in res:
    print(i, end=',', flush=False)
#执行结果: A,B,C,D,E,F


compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...      -->创建一个迭代器,它返回 data 中经 selectors 真值测试为 True 的元素。迭代器在两者较短的长度处停止。

res  = itertools.compress(data="ABCDEFG",selectors=[1, 0, 1, 0, 1, 1])   #1为True, 0为False
print(list(res))
#执行结果: ['A', 'C', 'E', 'F']


dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails    -->当序列不满足条件时返回该元素,之后的元素不作处理


groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)    -->返回 iterable 中连续的键和组

#groupby(): 把迭代器中相邻的重复元素挑出来放在一起:
res = itertools.groupby("AAABBBCCDDDDAAB")
for key,group in res:
    print(key, list(group))
"""
执行结果:
A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
D ['D', 'D', 'D', 'D']
A ['A', 'A']
B ['B']
"""


#groupby(): 使用函数,忽略大小写,让相同元素大小写key相同
res = itertools.groupby("AaaaBBbcCAAa", lambda x: x.upper())
for key, group in res:
    print(key, list(group))
"""
执行结果: 
A ['A', 'a', 'a', 'a']
B ['B', 'B', 'b']
C ['c', 'C']
A ['A', 'A', 'a']
"""


filterfalse(pred, seq) --> elements of seq where pred(elem) is False     -->返回 iterable 中 predicate(基于所写函数之上) 为 False 的元素

res = itertools.filterfalse(lambda x: x % 2, range(10))
print(list(res))
#执行结果: [0, 2, 4, 6, 8]


islice(seq, [start,] stop [, step]) --> elements from             -->相当于切片,返回从 iterable 里选中的元素,但与切片不同的时,不支持负值       seq[start:stop:step]

#islice(iterable,stop)   相当于切片,返回从 iterable 里选中的元素,但与切片不同的时,不支持负值
#islice(iterable,start,stop[,step])
res = itertools.islice('ABCDEFGH',3)
res1 = itertools.islice('ABCDEFGH',2,7,2)   #start=2,stop=7,step=2
print(list(res))    #['A', 'B', 'C']
print(list(res1))   #['C', 'E', 'G']


starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...            -->使用从可迭代对象中获取的参数来计算该函数

#startmap(function,iterable): 使用从可迭代对象中获取的参数来计算该函数
res = itertools.starmap(pow, [(2, 5), (3, 3), (4, 4)])   #返回序列的次幂值
print(list(res))
#执行结果: [32, 27, 256]


takewhile(pred, seq) --> seq[0], seq[1], until pred fails             -->与无穷迭代器count连用,生成符合条件的序列

res = itertools.count(1)
fn = itertools.takewhile(lambda x: x <= 10, res)    #返回小于等于10的自然数序列
print(list(fn))
#执行结果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...       -->相同长度的可迭代对象元素组合,超出部分用fillvalue对应值填充缺失

#zip_longest(iterables,fillvalue=None):相同长度的可迭代对象元素组合,超出部分用fillvalue对应值填充缺失

res = itertools.zip_longest('ABCDEF', 'XY',fillvalue='-')
print(list(res))
#执行结果:[('A', 'X'), ('B', 'Y'), ('C', '-'), ('D', '-'), ('E', '-'), ('F', '-')]
  • Combinatoric generators:  组合生成器

product(p, q, ... [repeat=1]) --> cartesian product    -->可迭代对象输入的笛卡儿积

#product(iterable,repeat=1):返回可迭代对象的笛卡尔积
res = itertools.product('ABCD','XY')
print(list(res))
#执行结果: [('A', 'X'), ('A', 'Y'), ('B', 'X'), ('B', 'Y'), ('C', 'X'), ('C', 'Y'), ('D', 'X'), ('D', 'Y')]


permutations(p[, r])        -->排列:连续返回由 iterable 元素生成长度为 r 的排列(已按字母顺序排列的子序列)


combinations(p, r)        -->组合:返回由输入 iterable 中元素组成长度为 r 的子序列,每个元素间不重复

res = itertools.combinations(iterable='ABCD',r=2)
print(list(res))
#执行结果: [('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]

res = itertools.combinations(iterable=range(4), r=3)
for i in res:
    print(i)
#执行结果: (0, 1, 2)(0, 1, 3)(0, 2, 3)(1, 2, 3)


combinations_with_replacement(p, r)   -->允许重复元素的组合:返回由输入 iterable 中元素组成的长度为 r 的子序列,允许每个元素可重复出现

  • more_itertools

#more_itertools
#一个值与可迭代对象合并
res = more_itertools.prepend(1, [3, 4, 5, 6])
for i in res:
    print(i)
#执行结果: 1 3 4 5 6
  • 相关示例:

#练习
"""
def pi(N):
    ' 计算pi的值 '
    # step 1: 创建一个奇数序列: 1, 3, 5, 7, 9, ...

    # step 2: 取该序列的前N项: 1, 3, 5, 7, 9, ..., 2*N-1.

    # step 3: 添加正负符号并用4除: 4/1, -4/3, 4/5, -4/7, 4/9, ...

    # step 4: 求和:
    return 3.14
"""
def pi(N):
    res = itertools.count(start=1,step=2)     #创建奇数列
    fn = itertools.takewhile(lambda x: x <= 2*N-1, res)   #取该数列的前N项
    sum = 0
    for i , value in enumerate(fn):
        sum += (-1)**i / value * 4      #添加正负符号并用4除 ,求和
    return sum

print(pi(10))
print(pi(100))
print(pi(1000))      #执行结果: 3.14