2012-04-19 13 views
1

私は検証のために使用するライブラリ/ユーティリティを書いています。私はいくつかの順序でそれらを消費する一連の要素とテスト対象システムを用意します。集合はすべての可能な入力を表し、システムはそれらの要素の有限シーケンスを受け取る。Pythonで長さMのN番目のシーケンスを計算する

有限シーケンスのセットは、私はセットのすべてのシーケンスを計算するが、代わりに以下を達成するため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(または他のモジュール)ショートカットに向かって私を指すことができますか?

答えて

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))] 
+0

これはよく見えますが、シーケンスの繰り返しを可能にするためには、combine_with_replacement(、)を使用すると思いますか? –

+0

@ JohnCarter、まあ、上記の_does_はシーケンスの繰り返しを可能にします。違いは、上で使用されたn次元のデカルト積では順序が重要であることです。 '(1,1,2)'と '(1,2,1)'が生成されます。あなたがそれを望まないなら、 'combined_with_replacement'が行く方法です。 – senderle

+0

明確化のためにありがとう。 –

関連する問題