在Python中计算长度为M的第N个序列

时间:2012-04-19 13:15:33

标签: python recursion set generator sequence

我正在编写一个我将用于验证的库/实用程序。我将有一组元素和一个测试系统按照某种顺序消耗它们。该集合代表所有可能的输入,系统将接收这些元素的有限序列。

由于有限序列的集合将是无限的,我不打算计算集合的所有序列,而是设想使用python生成器来完成以下任务:

def seq(s): # s is a set
  length = 0
  nth = 0
  # r = calculate nth sequence of length
  # if there are no more sequences of length, length += 1
  # else n += 1, yield r

我最终会将其扩展为单射和双射序列,但是现在该集合的元素可以出现任意次。

生成器是最好的方法吗?使用这样的生成器是否消除了从递归中获得的任何简单性?任何人都可以指向任何可能对我有帮助的itertools(或其他模块)捷径吗?

1 个答案:

答案 0 :(得分:2)

听起来你正在寻找itertools.product。我相信这会做你所要求的:

def seq(s):
    length = 1
    while True:
        for p in itertools.product(s, repeat=length):
            yield p
        length += 1

现在你可以这样做:

>>> zip(range(10), seq(set((1, 2, 3))))
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 1)), (4, (1, 2)), 
 (5, (1, 3)), (6, (2, 1)), (7, (2, 2)), (8, (2, 3)), (9, (3, 1))]

或者这个:

>>> test_seq = itertools.izip(itertools.count(), seq(set((1, 2, 3))))
>>> for i in range(10):
...     next(test_seq)
... 
(0, (1,))
(1, (2,))
(2, (3,))
(3, (1, 1))
(4, (1, 2))
(5, (1, 3))
(6, (2, 1))
(7, (2, 2))
(8, (2, 3))
(9, (3, 1))

使用其他itertools

也可以进一步压缩
>>> from itertools import chain, product, count
>>> s = set((1, 2, 3))
>>> test_seq = chain.from_iterable(product(s, repeat=n) for n in count(1))
>>> zip(range(10), test_seq)
[(0, (1,)), (1, (2,)), (2, (3,)), (3, (1, 1)), (4, (1, 2)), (5, (1, 3)), 
 (6, (2, 1)), (7, (2, 2)), (8, (2, 3)), (9, (3, 1))]