文章目录
- (一)itertools 的所有函数说明
- 无穷迭代器包含的 函数列表
- 1、count( start [,step])
- 2、cycle( iterable )
- 3、repeat( elem [,n] )
- 4 、accumulate( p [,func] )
- 5、chain( p, q, … )
- 6. chain.from_iterable(iterable)
- 7、compress(data, selectors)
- 8、dropwhile(func, iterable)
- 9、filterfalse(func, iterable)
- 10、groupby(iterable, key=None)
- 11、islice(iterable, start, stop[, step ])
- 12、starmap(function, iterable)
- 13、takewhile(predicate, iterable)
- 14、tee(iterable, n=2)
- 15、zip_longest(*iterables, fillvalue=None)
- 排列组合迭代器:
- 1、product(*iterables, repeat=1)
- 2、permutations(iterable, r=None)
- 3、combinations(iterable, r)
- 4、combinations_with_replacement(iterable, r)
(一)itertools 的所有函数说明
无穷迭代器包含的 函数列表
迭 代 器 | 说明 |
count( start [,step]) | 创建一个从 start 开始,步长为 step 的迭代器,默认为1。 |
cycle( iterable ) | 创建一个从 iterable 中 循环 取出元素的迭代器。 |
repeat( elem [,n] ) | 重复 elem元素 n次。 n为空时,重复无穷次。 |
accumulate( p [,func] ) | 创建一个迭代器,返回累加和或其他二元函数的累加结果。 |
chain( p, q, … ) | 把可迭代对象p, q 中的元素连接起来。 |
chain.from_iterable( iterable ) | 要求iterable对象中的元素也是可迭代的,然后把元素中元素创建一个迭代器 |
compress(data, selectors) | 创建一个迭代器,它返回data 中经selectors 真值测试为True 的元素。 |
dropwhile(predicate, iterable) | 创建一个迭代器,如果predicate 为true,迭代器丢弃这些元素,然后返回其他元素。 |
filterfalse(predicate, iterable) | 创建一个迭代器,只返回iterable 中predicate 为False 的元素。 |
groupby(iterable, key=None) | 创建一个迭代器,对里面的元素 按 key 进行分组。 |
islice(iterable, start, stop[, step ]) | 创建一个迭代器,返回从iterable 里选中的元素。如果start 不是0,跳过iterable 中的元素,直到到达start 这个位置。之后迭代器连续返回元素,除非step 设置的值很高导致被跳过。 |
starmap(function, iterable) | 类似 map(),function函数历遍 iterable中的元素。 |
takewhile(predicate, iterable) | 创建一个迭代器,只要predicate 为真就从可迭代对象中返回元素。 |
tee(iterable, n=2) | 从一个可迭代对象中返回n 个独立的迭代器。 |
zip_longest(*iterables, fillvalue=None) | 创建一个迭代器,从每个可迭代对象中收集元素。如果可迭代对象的长度未对齐,将根据fillvalue 填充缺失值。 |
1、count( start [,step])
创建一个从 start 开始,步长为 step 的迭代器,默认为1。
import itertools
"""生成一个 从 10 开始,步长为 2 的无穷迭代器。不知道如果超过了sys.maxsize,会怎样,没尝试过"""
for i in itertools.count(10,2):
print(i)
if i >= 30:
break
运行结果:
10
12
14
16
18
20
22
24
26
28
30
2、cycle( iterable )
创建一个迭代器,内容是不断循环的从 迭代对象 iterable 中取出的元素。
import itertools
for i in itertools.cycle('abc'):
print(i)
运行结果:
a
b
c
a
b
c
…… # 不断循环下去
3、repeat( elem [,n] )
创建一个迭代器, 内容是重复 n 次 elem 元素。如果没有 n 参数,则无限重复。
import itertools
for i in itertools.repeat('abc', 3):
print(i)
运行结果:
abc
abc
abc # 重复 3 次。
Process finished with exit code 0
4 、accumulate( p [,func] )
说明:参数 p 是一个迭代器,设里面的元素为 p0, p1, p2,p3 ……
func 默认是 求和。
返回一个迭代器 t,内容是 :
import itertools
list_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
it = itertools.accumulate(list_num)
print(list(it))
运行结果为:
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Process finished with exit code 0
5、chain( p, q, … )
创建一个迭代器,它首先返回第一个可迭代对象中所有元素,接着返回下一个可迭代对象中所有元素,直到耗尽所有可迭代对象中的元素。可将多个序列处理为单个序列。
import itertools
list_num = [1, 2, 3, 4, 5,]
list_cha = ['a', 'b', 'c', 'd']
it = itertools.chain(list_num,list_cha)
print(list(it))
运行结果:
[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd']
Process finished with exit code 0
6. chain.from_iterable(iterable)
创建一个迭代器,要求参数 iterable 中的每个元素还是可迭代的,它会把每个元素再迭代一次。
其实可以这样理解:这里的参数 iterable,就是上面 5 、chain( p, q, … ) 中 参数的“集合”, iterable = ( p, q, … )
import itertools
list_cha = ['aaa', 'bbb', 'ccc', [1,2,3]]
""" 会把 list_cha 中每个元素取出来,再对每个元素进行一次迭代。 """
it = itertools.chain.from_iterable(list_cha)
print(list(it))
运行结果:
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 1, 2, 3]
Process finished with exit code 0
7、compress(data, selectors)
创建一个迭代器,根据selectors 序列的值对data 序列的元素进行过滤。如果selector[0]为真,则保留data[0] ,如果selector[1]为真,则保留data[1] … 依此类推。迭代器在两者较短的长度处停止。
import itertools
list_num = [ 1, 0, True, 0, 1,]
list_cha = ['aaa', 'bbb', 'ccc', 'ddd']
""" 根据 list_num 对 list_cha 进行筛选 """
it = itertools.compress(list_cha, list_num)
print(list(it))
运行结果:
['aaa', 'ccc']
Process finished with exit code 0
8、dropwhile(func, iterable)
创建一个迭代器,如果 func 为 True,迭代器丢弃这些元素,直到 func 为 False,迭代过程立刻停止,返回从 False 处到结尾的所有元素。注意,迭代器在 func 首次为false 之前不会产生任何输出,所以可能需要一定长度的启动时间。
注解: 8 和 9 的函数主要是为了剔除元素,所有 把需要剔除的元素 传入判断函数,然后返回 真值 即可。
import itertools
list_num = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
def func(x):
if x > 5:
return False
else:
return True
""" 调用 func 函数对 list_num 中的元素进行判断,判断结果为真时,就丢弃这个元素。
当遇到 False 时,则停止判断,把后续的所有内容添加到生成的迭代器中。"""
it = itertools.dropwhile(func, list_num)
print(list(it))
运行结果:
[6, 7, 8, 1, 2]
9、filterfalse(func, iterable)
和 8、dropwhile(func, iterable) 类似,不过这个它会判断 iterable 中所有的元素。
创建一个迭代器,对 iterable 中每个元素进行判断,如果 func 为true,迭代器丢弃这些元素,然后返回其他元素。
如果 func 是None,则直接对元素进行 bool 值判读,删除 bool == True 的元素,保留 bool == False 的元素。
注解:8 和 9 的函数主要是为了剔除元素,所有 把需要剔除的元素 传入判断函数,然后返回 真值 即可。
import itertools
list_num = [1, 2, 3, 4, 5, 6, 7, 8, 0, 2]
def func(x):
if x > 5:
return False
else:
return True
""" 调用 func 函数对 list_num 中的每个元素进行判断,判断结果为真时,就丢弃这个元素。
保留 func 为 False 的元素。"""
it = itertools.filterfalse(func,list_num)
print(list(it))
运行结果为:
[6, 7, 8]
另外 当 func = None 是,filterfalse 会直接判断里面的元素的bool值,然后删除 bool == True 的值。如下:
import itertools
list_num = [1, 2, 3, False, 5, 6, 7, 8, 0, 2]
it = itertools.filterfalse(None,list_num)
print(list(it))
运行结果为:
[False, 0]
10、groupby(iterable, key=None)
创建一个 迭代器,里面的元素 是 按照 Key 进行分组的。
迭代器中的元素格式类似:{ key1: [a0,a1,…], key2: [b0,b1,…], key3: [c0,c1,…]}
key 对应的分组内容 也是一个 迭代器。
所以参数 key 得是一个函数,它能对 iterable 中的元素进行分类,return返回的就是key的名称。
注:使用 groupby() 函数之前,需对里面的元素按 key 进行排序。因为它分组是根据临近的元素,如果它们key一样就分到一组。
如下例子1:
情况1:里面的元素 已经 按 key 进行排序了。运行后得出的结果是正确分组的。
from itertools import groupby
# 字典中的元素,已经按 班级 排序好了。
dic = [{'class': '1 班', 'name':'小红'},
{'class': '1 班', 'name':'小明'},
{'class': '2 班', 'name':'李雷'},
{'class': '2 班', 'name':'韩梅梅'},
{'class': '3 班', 'name':'熊二'},
{'class': '3 班', 'name':'熊大'},
]
def func(i): # 定义一个 供 key 调用的函数,按return返回的值 进行分组。
return i['class']
ite = groupby(dic, key=func)
for k, item in ite:
# 因为 item 也是一个 迭代器,所以可以用 list 把它的元素显示出来。
print(f'key 为:{k}; 对应分组的内容为:{list(item)}')
运行结果为:
key 为:1 班; 对应分组的内容为:[{'class': '1 班', 'name': '小红'}, {'class': '1 班', 'name': '小明'}]
key 为:2 班; 对应分组的内容为:[{'class': '2 班', 'name': '李雷'}, {'class': '2 班', 'name': '韩梅梅'}]
key 为:3 班; 对应分组的内容为:[{'class': '3 班', 'name': '熊二'}, {'class': '3 班', 'name': '熊大'}]
Process finished with exit code 0
情况2:里面的元素 未 按 key 进行排序。运行后得出的结果是没有正确分组。
from itertools import groupby
dic = [{'class': '1 班', 'name':'小红'},
{'class': '3 班', 'name':'熊二'}, # 把 班级 3 放在班级 1中间。
{'class': '1 班', 'name':'小明'},
{'class': '2 班', 'name':'李雷'},
{'class': '2 班', 'name':'韩梅梅'},
{'class': '3 班', 'name':'熊大'},
]
def func(i):
return i['class']
ite = groupby(dic, key=func)
for k, item in ite:
print(f'key 为:{k}; 对应分组的内容为:{list(item)}')
运行结果为(不是我们想要的,1班 和 3班 没有各自分组到一起):
key 为:1 班; 对应分组的内容为:[{'class': '1 班', 'name': '小红'}]
key 为:3 班; 对应分组的内容为:[{'class': '3 班', 'name': '熊二'}]
key 为:1 班; 对应分组的内容为:[{'class': '1 班', 'name': '小明'}]
key 为:2 班; 对应分组的内容为:[{'class': '2 班', 'name': '李雷'}, {'class': '2 班', 'name': '韩梅梅'}]
key 为:3 班; 对应分组的内容为:[{'class': '3 班', 'name': '熊大'}]
Process finished with exit code 0
举例2:
from itertools import groupby
lst=[30,20,99,50,60,65,80,90,85,88]
def func(num):
if num < 60:
return '不及格'
elif num <=70:
return '及格'
else:
return '良好'
ite = groupby(sorted(lst), key=func) # 用sorted() 对 lst 中元素先进行排序。
for k, item in ite:
print(f'key 为:{k}; 对应分组的内容为:{list(item)}')
运行结果为:
key 为:不及格; 对应分组的内容为:[20, 30, 50]
key 为:及格; 对应分组的内容为:[60, 65]
key 为:良好; 对应分组的内容为:[80, 85, 88, 90, 99]
Process finished with exit code 0
11、islice(iterable, start, stop[, step ])
创建一个迭代器,内容是可以看作是对 iterable 进行类似列表的切片操作。
1、当只有两个参数时,第二个位置参数就是 截止 stop 的位置。
from itertools import islice
a = range(1,21)
ite = islice(a,10) # 取到索引为10的位置,不包括索引为10的元素。
print(list(ite))
运行结果为:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Process finished with exit code 0
2、当只有3个参数时,元素 就是从 第二个参数,取到第三个参数。
from itertools import islice
a = range(1,21)
ite = islice(a,5,15) # 索引5的值是6,索引15的值是16(不包括)
print(list(ite))
运行结果为:
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Process finished with exit code 0
3、当有4个参数时:
from itertools import islice
a = range(1,21)
ite = islice(a,0,None,2) # None 表示取到结尾,2 表示步长为2
print(list(ite))
运行结果:
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
Process finished with exit code 0
4、当 start 参数大于等于 iterable 中的元素个数时,返回一个空的迭代器。
from itertools import islice
a = range(1,21) # 生成的最大索引值为19
ite = islice(a,20,None,2) # 从索引值为20的位置开始取……
print(list(ite))
[]
Process finished with exit code 0
12、starmap(function, iterable)
功能和 内置函数 map() 类似,它会创建一个 迭代器,元素是 function 历遍 iterable 的返回值。只不过 starmap() 会对每个元素 再进行一次迭代,所以它会要求每个元素也是可迭代的。
import itertools
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [10, 11, 12, 13, 14, 15]
a_2 = [(1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9),(10,10)]
a_1 = [(1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,), (10,)]
# 只需要一个参数。
def func_1(x):
return pow(x,2)
# 解包参数。
def func_jiebao(x):
a, b = x # 对 x 进行解包
return a+b
# 需要两个参数。
def func_2(x,y):
return x+y
""" ======= 一、内置函数 map() 的使用 ==========="""
# 1、当调用函数 只需要1个参数时。 这个使用应该没什么问题 ^ ^
res = map(func_1, a)
print(list(res)) # >>> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 2、传入的是一个参数,但传入的这个参数是可以解包的。
res = map(func_jiebao, a_2)
print(list(res)) # >>> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# 3、当调用函数 需要2个参数时,可传入两个可迭代对象,当短的迭代对象中元素迭代完后,就停止 map 了。
res = map(func_2, a, b)
print(list(res)) # >>> [11, 13, 15, 17, 19, 21]
""" ======= 二、itertools函数 starmap() 的使用 ==========="""
# 1、当调用函数 只需要1个参数时,可用 a_1,不能用 a。
# 因为 starmap() 会对每个元素 再进行一次迭代,所以它会要求每个元素也是可迭代的。
ite_1 = itertools.starmap(func_1, a_1)
print(list(ite_1)) # >>> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 2、当调用函数 需要多个参数时,它会自动的对每个元素进行解包。
ite_2 = itertools.starmap(func_2, a_2)
print(list(ite_2)) # >>> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
13、takewhile(predicate, iterable)
takewhile() 与 dropwhile() 功能刚好相反。
takewhile() 会保留 func 返回True的元素,直到遇到使 func 返回 False 的元素,迭代过程立刻停止,并丢弃这个元素及之后的所有元素。
import itertools
a = [1, 4, 6, 4, 1]
def func(i):
if i <= 5:
return True
else:
return False
ite = itertools.takewhile(func, a)
print(list(ite)) # >>> [1, 4]
14、tee(iterable, n=2)
相当于复制 n 个 迭代器。默认n=2。
import itertools
b = ['aa', 'bb', 'cc', 'dd']
ite = itertools.tee(b,3)
for i in ite:
print(list(i))
从下面的运行结果中,可看出 ite 包含了 三个一样的迭代器:
['aa', 'bb', 'cc', 'dd']
['aa', 'bb', 'cc', 'dd']
['aa', 'bb', 'cc', 'dd']
15、zip_longest(*iterables, fillvalue=None)
类似内置 的 zip() 函数。
import itertools
a = [1, 2, 3, 4, 5, 6, 7, 8,]
b = [10, 11, 12, 13, 14, 15]
z = zip(a,b) # 按 短的 b 来合并。
print(list(z)) # >>> [(1, 10), (2, 11), (3, 12), (4, 13), (5, 14), (6, 15)]
""" 按长的 a 来 合并,b中元素不够,就用 fillvalue 填充。"""
ite_z = itertools.zip_longest(a, b, fillvalue=0)
print(list(ite_z))
# 运行结果为:
# >>> [(1, 10), (2, 11), (3, 12), (4, 13), (5, 14), (6, 15), (7, 0), (8, 0)]
ite_z = itertools.zip_longest(a, b, fillvalue=None)
print(list(ite_z))
# 运行结果为:
# >>> [(1, 10), (2, 11), (3, 12), (4, 13), (5, 14), (6, 15), (7, None), (8, None)]
排列组合迭代器:
迭代器 | 说明 |
product(*iterables, repeat=1) | 用来生成 *iterables 各元素之间的不同组合。 |
permutations(iterable, r=None) | iterable 中取出 r 个元素进行有序的排列组合。 |
combinations(iterable, r) | 用来在 iterable 中,无放回的取出 r 个元素进行无序排列组合。 |
combinations_with_replacement(iterable, r) | 用来在 iterable 中,有放回的取出 r 个元素进行无序排列组合。 |
1、product(*iterables, repeat=1)
product() 用来生成 *iterables 各元素之间的不同组合,
但各 组合中元素的顺序 是按参数的先后顺序固定的。
比如:下面代码生成的组合, 'ABCD’的元素一定在‘xy’ 之前,不可能出现在x或y之后。
它们之间的 组合数 可以这样思考:
1号箱子存放了“A、B、C、D”四个元素,
2号箱子存放了“x、y”两个元素,
先从 1号 箱随机取一个数,有 4 种取法。
再从 2号 箱随机取一个数,有 2 种取法。
所以它们的组合数为 4 x 2 = 8 种。
import itertools
ite = itertools.product('ABCD', 'xy', repeat=1)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:8
[('A', 'x'), ('A', 'y'), ('B', 'x'), ('B', 'y'),
('C', 'x'), ('C', 'y'), ('D', 'x'), ('D', 'y')]
当 repeat >= 2 时
1、product() 会先对 参数中的各个迭代器的元素进行组合,就是 repeat=1 所生成的样子,我们先给它命名为 ”初始组合“。
注:如果参数只有一个迭代器,那它的“初始组合”就是它自身各个元素。
2、按 repeat = n 中 n 的大小,对”初始组合“进行”复制“,加上”初始组合“一共n份。
3、对这 n 份”初始组合“中的元素,进行组合。
4、最终的组合数为:(参数中各迭代器元素数量的乘积)^ (repeat 值)
所以下方代码的组合数量为:4 ^ 2= 16
import itertools
ite = itertools.product('ABCD', repeat=2)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:16
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('B', 'D'),
('C', 'A'), ('C', 'B'), ('C', 'C'), ('C', 'D'), ('D', 'A'), ('D', 'B'), ('D', 'C'), ('D', 'D')]
原理如下:
当 n = 3 时, 就会在此基础上再进行一次组合:
2、permutations(iterable, r=None)
permutations(iterable, r=None) 函数用来在 iterable 中取出 r 个元素进行排列组合,
各个排列组合中的元素有先后顺序区别,相当于
当 r = None 时,就是对 iterable 中的所有元素进行排列。
import itertools
ite = itertools.permutations('ABCD', 2)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:12
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'A'), ('B', 'C'), ('B', 'D'),
('C', 'A'), ('C', 'B'), ('C', 'D'), ('D', 'A'), ('D', 'B'), ('D', 'C')]
注:即使元素的值相同,不同位置的元素也被认为是不同的。如果元素值都不同,每个排列中的元素值不会重复。
如下:
import itertools
ite = itertools.permutations('ABB', 2)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:6
[('A', 'B'), ('A', 'B'), ('B', 'A'), ('B', 'B'), ('B', 'A'), ('B', 'B')]
3、combinations(iterable, r)
该函数用来在 iterable 中取出 r 个元素进行无序排列组合,各个排列组合中的元素无先后顺序区别。
相当于 :
即可看成: 一个盒子里有r个不同的小球,从中一把抓出 r 个小球,看看有多少种小球的组合。
当 r = 0 时,返回一个迭代器,里面只有一个元素,且该元素为空元组 ( )。
当 r > 参数中迭代器元素的数量时,返回一个空迭代器。
注:即使元素的值相同,不同位置的元素也被认为是不同的。如果元素值都不同,每个排列中的元素值不会重复,同 permutations()。
import itertools
ite = itertools.combinations('ABCD', 2)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:6
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
4、combinations_with_replacement(iterable, r)
这个就是“可重组合”,
可看成: 先从一个盒子里先抓出一 个小球,把小球放回后,再接着抓一次,重复r次后,获得的组合。
且这个组合中的元素会被去重,即(A,B) 和 (B,A) 会被当成相同的元素,只保留一个。
当 r = 0 时,返回一个迭代器,里面只有一个元素,且该元素为()。
注:即使元素的值相同,不同位置的元素也被认为是不同的。如果元素值都不同,每个排列中的元素值不会重复。
import itertools
ite = itertools.combinations_with_replacement('ABCD', 2)
lite = list(ite)
print(f'长度为:{len(lite)}')
print(lite)
运行结果为:
长度为:10
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'B'),
('B', 'C'), ('B', 'D'), ('C', 'C'), ('C', 'D'), ('D', 'D')]