第三章:算法-itertools:迭代器函数-合并输入

3.2.6 合并输入
accumulate()函数处理输入迭代器,向一个函数传递第n和n+1个元素,并且生成返回值而不是某个输入。合并两个值的默认函数会将两个值相加,所有accumulate()可以用来生成一个数值输入序列的累加和。

from itertools import *

print(list(accumulate(range(5))))
print(list(accumulate('abcde')))

用于非整数值序列时,结果取决于将两个元素“相加”是什么含义。这个脚本中的第二个例子显示了当accumulate()接收到一个字符串输入时,每个响应都将是该字符串的一个前缀,而且长度不断增加。
运行结果:

[0, 1, 3, 6, 10]
[‘a’, ‘ab’, ‘abc’, ‘abcd’, ‘abcde’]

accumulate()可以与任何取两个输入值的函数结合来的到不同的结果。

from itertools import *

def f(a,b):
    print(a,b)
    return b + a + b

print(list(accumulate('abcde',f)))

这个例子以一种特殊的方式合并字符串值,会生成一系列(无意义的)回文。每一步调用f()时,它都会打印accumulate()传入的输入值。
运行结果:

a b
bab c
cbabc d
dcbabcd e
[‘a’, ‘bab’, ‘cbabc’, ‘dcbabcd’, ‘edcbabcde’]

迭代处理多个序列的嵌套for循环通常可以被替换为product(),它会生成一个迭代器,值为输入值集合的笛卡尔积。

from itertools import *
import pprint

FACE_CARDS = ('J','Q','K','A')
SUITS = ('H','D','C','S')

DECK = list(product(
    chain(range(2,11),FACE_CARDS),
    SUITS,
    )
)

for card in DECK:
    print('{:>2}{}'.format(*card),end=' ')
    if card[1] == SUITS[-1]:
        print()

product()生成的值是元组,成员取自作为参数传入的各个迭代器(按其传入的顺序)。返回的第一个元组包含各个迭代器的第一个值。传入product()的最后一个迭代器最先处理,接下来处理倒数第二个迭代器,依次类推。结果是按第一个迭代器、下一个迭代器等的顺序得到的返回值。
在这个例子中,扑克牌首先按牌面大小排序,然后按花色排序。
运行结果:

2H 2D 2C 2S
3H 3D 3C 3S
4H 4D 4C 4S
5H 5D 5C 5S
6H 6D 6C 6S
7H 7D 7C 7S
8H 8D 8C 8S
9H 9D 9C 9S
10H 10D 10C 10S
JH JD JC JS
QH QD QC QS
KH KD KC KS
AH AD AC AS

要改变这些扑克牌的顺序,需要改变传入product()的参数的顺序。

from itertools import *
import pprint

FACE_CARDS = ('J','Q','K','A')
SUITS = ('H','D','C','S')

DECK = list(product(
    SUITS,
    chain(range(2,11),FACE_CARDS),
    )
            )

for card in DECK:
    print('{:>2}{}'.format(card[1],card[0]),end=' ')
    if card[1] == FACE_CARDS[-1]:
        print()

这个例子中的打印循环会查找一个A而不是黑桃,然后增加一个换行使输出分行显示。
运行结果:

2H 3H 4H 5H 6H 7H 8H 9H 10H JH QH KH AH
2D 3D 4D 5D 6D 7D 8D 9D 10D JD QD KD AD
2C 3C 4C 5C 6C 7C 8C 9C 10C JC QC KC AC
2S 3S 4S 5S 6S 7S 8S 9S 10S JS QS KS AS

要计算一个序列与自身的积,可以指定输入重复多次。

from itertools import *

def show(iterable):
    for i,item in enumerate(iterable,1):
        print(item,end=' ')
        if (i % 3) == 0:
            print()
    print()

print('Repeat 2:\n')
show(list(product(range(3),repeat=2)))

print('Repeat 3:\n')
show(list(product(range(3),repeat=3)))

由于重复一个迭代器就像把同一个迭代器传入多次,product()生成的每个元组所包含的元素个数就等于重复计数器。
运行结果:

Repeat 2:

(0, 0) (0, 1) (0, 2)
(1, 0) (1, 1) (1, 2)
(2, 0) (2, 1) (2, 2)

Repeat 3:

(0, 0, 0) (0, 0, 1) (0, 0, 2)
(0, 1, 0) (0, 1, 1) (0, 1, 2)
(0, 2, 0) (0, 2, 1) (0, 2, 2)
(1, 0, 0) (1, 0, 1) (1, 0, 2)
(1, 1, 0) (1, 1, 1) (1, 1, 2)
(1, 2, 0) (1, 2, 1) (1, 2, 2)
(2, 0, 0) (2, 0, 1) (2, 0, 2)
(2, 1, 0) (2, 1, 1) (2, 1, 2)
(2, 2, 0) (2, 2, 1) (2, 2, 2)

permutations()函数从输入迭代器生成元素,这些元素以给定长度的排列形式组合。默认地它会生成所有排列的全集。

from itertools import *

def show(iterable):
    first = None
    for i,item in enumerate(iterable,1):
        if first != item[0]:
            if first is not None:
                print()
            first = item[0]
        print(''.join(item),end=' ')
    print()

print('All permutations:\n')
show(permutations('abcd'))

print('\nPairs:\n')
show(permutations('abcd',r=2))

可以使用r参数限制返回的各个排列的长度和个数。
运行结果:

All permutations:

abcd abdc acbd acdb adbc adcb
bacd badc bcad bcda bdac bdca
cabd cadb cbad cbda cdab cdba
dabc dacb dbac dbca dcab dcba

Pairs:

ab ac ad
ba bc bd
ca cb cd
da db dc

为了将值限制为唯一的组合而不是排列,可以使用combinations()。只要输入的成员是唯一的,输出就不会包含任何重复的值。

from itertools import *

def show(iterable):
    first = None
    for i ,item in enumerate(iterable,1):
        if first != item[0]:
            if first is not None:
                print()
            first = item[0]
        print(''.join(item),end=' ')
    print()

print('Unique pairs:\n')
show(combinations('abcd',r=2))

与排列不同,combinations()的r参数是必要参数。
运行结果:

Unique pairs:

ab ac ad
bc bd
cd

尽管combinations()不会重复单个的输入元素,但有时可能也需要考虑包含重复元素的组合。对于这种情况,可以使用combinations_with_replacement()。

from itertools import *

def show(iterable):
    first = None
    for i,item in enumerate(iterable,1):
        if first != item[0]:
            if first is not None:
                print()
            first = item[0]
        print(''.join(item),end=' ')
    print()

print('Unique pairs:\n')
show(combinations_with_replacement('abcd',r=2))

在这个输出中,每个输入元素会与自身以及输入序列的所有其他成员配对。
运行结果:

Unique pairs:

aa ab ac ad
bb bc bd
cc cd
dd

你可能感兴趣的:(Python标准库)