Python实现排列和组合(itertools模块)

itertools迭代器的特点是:惰性求值(Lazy evaluation),即只有当迭代至某个值时,它才会被计算,这个特点使得迭代器特别适合于遍历大文件或无限集合等,因为我们不用一次性将它们存储在内存中。
Python 内置的 itertools 模块包含了一系列用来产生不同类型迭代器的函数或类,这些函数的返回都是一个迭代器,我们可以通过 for 循环来遍历取值,也可以使用 next() 来取值。
itertools 模块提供的迭代器函数有以下几种类型:

  • 无限迭代器:生成一个无限序列,比如自然数序列 1, 2, 3, 4, …;
  • 有限迭代器:接收一个或多个序列(sequence)作为参数,进行组合、分组和过滤等;
  • 组合生成器:序列的排列、组合,求序列的笛卡儿积等;

以下代码为python3.5的环境
一: 组合生成器(本文的中心)

1.1 组合:
不包括自身元素

#coding:utf-8
import itertools 
#使用combinations方法
ls = itertools.combinations('ABC', 2) 
#ls = itertools.combinations(['A','B','C'], 2) 
#遍历所有组合情况,ls是个迭代器
for l in ls:    
    print(l)
   
ls = [list(iter) for _, iter in enumerate(itertools.combinations('ABC', 2))]
print(ls)
ls = [''.join(iter) for _, iter in enumerate(itertools.combinations('ABC', 2))]
print(ls)

输出:

('A', 'B')
('A', 'C')
('B', 'C')
[['A', 'B'], ['A', 'C'], ['B', 'C']]
['AB', 'AC', 'BC']

包括自身元素

#coding:utf-8
import itertools
 #使用combinations_with_replacement方法
ls = itertools.combinations_with_replacement(['A','B','C'], 2)
ls = itertools.combinations_with_replacement('ABC', 2)
#遍历所有组合情况
for l in ls:
    print(l)
ls = [list(iter) for _, iter in enumerate(itertools.combinations_with_replacement('ABC', 2))]
print(ls)
ls = [''.join(iter) for _, iter in enumerate(itertools.combinations_with_replacement('ABC', 2))]
print(ls)

输出:

('A', 'A')
('A', 'B')
('A', 'C')
('B', 'B')
('B', 'C')
('C', 'C')
[['A', 'A'], ['A', 'B'], ['A', 'C'], ['B', 'B'], ['B', 'C'], ['C', 'C']]
['AA', 'AB', 'AC', 'BB', 'BC', 'CC']

1.2 排列

#coding:utf-8
import itertools
#使用permutations方法
ls = itertools.permutations(['A','B','C'], 2)
ls = itertools.permutations('ABC', 2)
#遍历所有组合情况
for l in ls:
    print(l)

ls = [list(iter) for _, iter in enumerate(itertools.permutations('ABC', 2))]
print(ls)
ls = [''.join(iter) for _, iter in enumerate(itertools.permutations('ABC', 2))]
print(ls)

输出:

('A', 'B')
('A', 'C')
('B', 'A')
('B', 'C')
('C', 'A')
('C', 'B')
[['A', 'B'], ['A', 'C'], ['B', 'A'], ['B', 'C'], ['C', 'A'], ['C', 'B']]
['AB', 'AC', 'BA', 'BC', 'CA', 'CB']

1.3 笛卡尔积

#coding:utf-8
from itertools import product
#使用product方法
for item in product('ABC', 'xy'):
    print(item)

print(list(product('ab', range(3))))
print(list(product((0, 1), (0, 1), (0, 1))))
#repeat 是一个关键字参数,用于指定重复生成序列的次数
print(list(product('ABC', repeat=2)))

输出:

('A', 'x')
('A', 'y')
('B', 'x')
('B', 'y')
('C', 'x')
('C', 'y')
[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2)]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]

二、无限迭代器

itertools 模块提供了三个函数(事实上,它们是类)用于生成一个无限序列迭代器:

  • count(firstval=0, step=1)
    创建一个从 firstval (默认值为 0) 开始,以 step (默认值为 1) 为步长的的无限整数迭代器
  • cycle(iterable)
    对 iterable 中的元素反复执行循环,返回迭代器
  • repeat(object [,times]
    反复生成 object,如果给定 times,则重复次数为 times,否则为无限

2.1 count

#coding:utf-8
import itertools
nums = itertools.count()
for i in nums:
    if i > 3:
        break
    print(i)
print('###')    
nums = itertools.count(10, 2)
for i in nums:
    if i > 16:
        break
    print(i)

输出:

0
1
2
3
###
10
12
14
16

2.2 cycle

#coding:utf-8
import itertools

cycle_strings = itertools.cycle('ABC')
i = 1
for string in cycle_strings:
     if i == 7:
        break
     print(i, string)
     i += 1

输出:

1 A
2 B
3 C
4 A
5 B
6 C

2.3 repeat

#coding:utf-8
import itertools

for item in itertools.repeat('hello world', 3):
    print(item)
for item in itertools.repeat([1, 2, 3, 4], 3):
    print(item)

输出:

hello world
hello world
hello world
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]

三、有限迭代器

itertools 模块提供了多个函数(类),接收一个或多个迭代对象作为参数,对它们进行组合、分组和过滤等:

  • chain()
  • compress()
  • dropwhile()
  • groupby()
  • filter()
  • filterfalse()
  • islice()
  • map()
  • starmap()
  • tee()
  • takewhile()
  • zip()
  • zip_longest()

3.1 chain

#coding:utf-8
from itertools import chain
#接收多个可迭代对象作为参数,将它们『连接』起来,作为一个新的迭代器返回。
for item in chain([1, 2], ['a', 'b']):
    print(item)
#接收一个可迭代对象作为参数,返回一个迭代器
for item in chain.from_iterable('ABC'):
    print(item)

输出:

1
2
a
b
A
B
C

3.2 compress

#coding:utf-8
#compress(data, selectors)
#可用于对数据进行筛选,当 selectors 的某个元素为 true 时,则保留 data 对应位置的元素,否则去除:
from itertools import compress
print(list(compress('ABCDEF', [1, 1, 0, 1, 0, 1])))
print(list(compress('ABCDEF', [1, 1, 0, 1])))
print(list(compress('ABCDEF', [True, False, True])))

输出:

['A', 'B', 'D', 'F']
['A', 'B', 'D']
['A', 'C']

3.3 dropwhile

#dropwhile(predicate, iterable)
#predicate 是函数,iterable 是可迭代对象。对于 iterable 中的元素,如果 predicate(item) 为 true,则丢弃该元素,否则返回该项及所有后续项。
from itertools import dropwhile
print(list(dropwhile(lambda x: x < 5, [1, 3, 6, 2, 1])))
print(list(dropwhile(lambda x: x > 3, [2, 1, 6, 5, 4])))

输出:

[6, 2, 1]
[2, 1, 6, 5, 4]

3.4 groupby

#groupby(iterable[, keyfunc])
#iterable 是一个可迭代对象,keyfunc 是分组函数,用于对 iterable 的连续项进行分组,如果不指定,则默认对 iterable 中的连续相同项进行分组,返回一个 (key, sub-iterator) 的迭代器。
from itertools import groupby

for key, value_iter in groupby('aaabbbaaccd'):
    print(key, ':', list(value_iter))
    
data = ['a', 'bb', 'ccc', 'dd', 'eee', 'f']
for key, value_iter in groupby(data, len):# 使用 len 函数作为分组函数
    print(key, ':', list(value_iter))
    
data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']
for key, value_iter in groupby(data, len):
    print(key, ':', list(value_iter))

输出:

a : ['a', 'a', 'a']
b : ['b', 'b', 'b']
a : ['a', 'a']
c : ['c', 'c']
d : ['d']

1 : ['a']
2 : ['bb']
3 : ['ccc']
2 : ['dd']
3 : ['eee']
1 : ['f']

1 : ['a']
2 : ['bb', 'cc']
3 : ['ddd', 'eee']
1 : ['f']

3.5 filter

#python2.7 from itertools import ifilter
#filter(function or None, sequence)
#将 iterable 中 function(item) 为 True 的元素组成一个迭代器返回,如果 function 是 None,则返回 iterable 中所有计算为 True 的项。
print(list(filter(lambda x: x < 6, range(10))))
print(list(filter(None, [0, 1, 2, 0, 3, 4])))

输出:

[0, 1, 2, 3, 4, 5]
[1, 2, 3, 4]

3.6 filterfalse

#python2.7 为 ifilterfalse
#filterfalse 的使用形式和 filter 类似,它将 iterable 中 function(item) 为 False 的元素组成一个迭代器返回,如果 function 是 None,则返回 iterable 中所有计算为 False 的项。
from itertools import filterfalse
print(list(filterfalse(lambda x: x < 6, range(10))))
print(list(filter(None, [0, 1, 2, 0, 3, 4])))

输出:

[6, 7, 8, 9]
[1, 2, 3, 4]

3.7 islice

#islice(iterable, [start,] stop [, step]) 
#iterable 是可迭代对象,start 是开始索引,stop 是结束索引,step 是步长,start 和 step 可选
from itertools import count, islice
print(list(islice([10, 6, 2, 8, 1, 3, 9], 5)))
print(list(islice(count(), 6)))
print(list(islice(count(), 3, 10)))
print(list(islice(count(), 3, 10 ,2)))

输出:

[10, 6, 2, 8, 1]
[0, 1, 2, 3, 4, 5]
[3, 4, 5, 6, 7, 8, 9]
[3, 5, 7, 9]

3.8 map

#from itertools import imap(python2.7),python3 直接 map
#map(func, iter1, iter2, iter3, ...)
#map 返回一个迭代器,元素为 func(i1, i2, i3, ...),i1,i2 等分别来源于 iter, iter2。
print(list(map(str, [1, 2, 3, 4])))
print(list(map(pow, [2, 3, 10], [4, 2, 3])))

输出:

['1', '2', '3', '4']
[16, 9, 1000]

3.9 tee

#tee(iterable [,n])
#tee 用于从 iterable 创建 n 个独立的迭代器,以元组的形式返回,n 的默认值是 2。
from itertools import tee
iter1, iter2 = tee('abcde')# n 默认为 2,创建两个独立的迭代器
print(list(iter1))
print(list(iter2))
tee('abc', 3)  # 创建三个独立的迭代器

输出:

['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e']

3.10 takewhile

#takewhile(predicate, iterable)
#predicate 是函数,iterable 是可迭代对象。对于 iterable 中的元素,如果 predicate(item) 为 true,则保留该元素,只要 predicate(item) 为 false,则立即停止迭代。
from itertools import takewhile

print(list(takewhile(lambda x: x < 5, [1, 3, 6, 2, 1])))
print(list(takewhile(lambda x: x > 3, [2, 1, 6, 5, 4])))

输出:

[1, 3]
[]

3.11 zip

#from itertools import izip(python2.7),python3直接zip
#zip 用于将多个可迭代对象对应位置的元素作为一个元组,将所有元组『组成』一个迭代器,并返回。它的使用形式如下:
#zip(iter1, iter2, ..., iterN)
for item in zip('ABCD', 'xy'):
    print(item)
for item in zip([1, 2, 3], ['a', 'b', 'c', 'd', 'e']):
    print(item)

输出:

('A', 'x')
('B', 'y')
(1, 'a')
(2, 'b')
(3, 'c')

3.12 zip_longest

#zip_longest 跟 zip 类似,但迭代过程会持续到所有可迭代对象的元素都被迭代完。python2.7为from itertools import izip_longest 
#zip_longest(iter1, iter2, ..., iterN, [fillvalue=None])
from itertools import zip_longest

for item in zip_longest('ABCD', 'xy'):
    print(item)
for item in zip_longest('ABCD', 'xy', fillvalue='-'):
    print(item)

输出:

('A', 'x')
('B', 'y')
('C', None)
('D', None)
('A', 'x')
('B', 'y')
('C', '-')
('D', '-')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值