2016-04-21 38 views
2

次の簡単なコードは、長さ3の200要素の可能な組み合わせを示しています。iterable(itertools.combinations)をリストに変換せずにシャッフルする組み合わせ

from itertools import combinations 
comb = combinations(range(200), 3) 

最初のN個の組み合わせを選択するために、ランダムな順序で組み合わせを取得したいと考えています。

comb = list(comb) # This might be huge and give a memory error 
random.shuffle(comb) 
N = 10 
comb = comb[:10] # get only the first N random combinations 

Nランダムな組み合わせを得るために他の方法があります:私はリストに櫛を変換すると、次のようにそれをシャッフルする場合は、リストがあまりにも多くの要素が含まれている可能性があるのでしかし、私は、メモリエラーを得ることができますか? (つまり、itertools.combinationsによって生成された順序ではありません)。

答えて

4

可能な組み合わせはC(200, 3) = 1313400です。あなたが言及したように、この数字はcombinatorial explosionのために手に入らないこともあります。たとえば、3つの要素の代わりに4を選択すると、組み合わせの数は約50倍になります(64684950)。これらの組み合わせからランダムに選択する代わりに、可能な組み合わせをランダムに作成することができます。

これらの組み合わせを構築するには、ランダムライブラリのrandom.sampleを使用できます。 random.sample(range(200), 3)は、これらの1313400の組み合わせの1つをランダムに生成します。もう一度呼び出すと、別の組み合わせが生成されます。

二つの問題があります

  1. 順序([1、2、3] [1、3、2]とは異なる)random.sampleに重要です。組み合わせて、そうではありません。これを解決するにはsorted()を使用できます。
  2. random.sampleは、次の3つの数値を独立して生成します。したがって、異なる反復で生成された組み合わせは同じであってもよい。この例では(≒0.0000343)はほとんどありませんが、セットを使用して組み合わせを保存すると、一意の組み合わせのみが保存されます。

以下は、10個の異なる組み合わせを生成します。私はイテレータはこの場合のいずれかのadventagesを持っていないと思う@mprat

import random 
combs = set() 
N = 10 
while len(combs) < N: 
    combs.add(tuple(sorted(random.sample(range(200), 3)))) 
+0

この答えはイテレータ – mprat

+0

の特性を利用しません。以下の関数では、 'pool = tuple(iterable)'を代入しています。 'random_combination(comb、10)'で関数を呼び出すと、すべての可能な組み合わせが生成され、poolという変数に格納されます。これはOPが避けようとしていたものです。 – ayhan

+0

@mprat:これは基本的にストリーム操作ではありません。イテレータには利点がありません。あなたの答えは、itertoolsドキュメンテーションから取られていても、itertoolsまたはiteratorオペレーションを全く使用しません。 'itertools.combinations'に関連した作業だからです。 – user2357112