6

パイソンの質問です。オブジェクトの大きな配列を生成していますが、これは小さなランダム サンプルを作成するだけで済みます。問題のオブジェクトを実際に生成するには時間がかかるため、生成する必要のないオブジェクトをスキップして、サンプリングされたオブジェクトのみを明示的に作成することはできないかと思います。

言い換えれば、私は今持っています

a = createHugeArray()
s = random.sample(a,len(a)*0.001)

これはかなり無駄です。私はもっ​​と怠け者のようなものを好むだろう

a = createArrayGenerator()
s = random.sample(a,len(a)*0.001)

これが機能するかどうかはわかりません。random.sample のドキュメントはあまり明確ではありませんが、xrange が非常に高速であると言及されているため、動作する可能性があると思われます。配列の作成をジェネレーターに変換するのは少し面倒なので (ジェネレーターに関する私の知識は非常にさびしいです)、これが機能するかどうかを事前に知りたいです。:)

私が見ることができる別の方法は、xrange を介してランダムなサンプルを作成し、実際にインデックスによって選択されたオブジェクトのみを生成することです。ただし、生成されるインデックスは任意で不必要であるため、これはあまりきれいではありません。また、generateHugeArray メソッドでこれをサポートするには、かなりハックなロジックが必要になります。

ボーナス ポイント: random.sample は実際にどのように機能しますか? 特に、xrange のようなジェネレーターのように、人口のサイズが事前にわからない場合、どのように機能しますか?

4

4 に答える 4

2

インデックスが順列にどのようにマッピングされるかを理解することを避ける方法はないようです。これがわからない場合、配列からランダムなオブジェクトを作成するにはどうすればよいでしょうか? xrange()自分で提案したトリックを使用するか、__getitem__()__len__()メソッドを定義するクラスを実装し、このクラスの と オブジェクトをpopulationへの引数として渡しますrandom.sample()

その他のコメント:

  • createHugeArray() をジェネレーターに変換しても何もrandom.sample()得られません。もはや機能しません。をサポートするオブジェクトが必要len()です。

  • したがって、最初から母集団の要素数を知る必要があります

  • 実装には 2 つの異なるアルゴリズムがあり、メモリ使用量が少ない方を選択します。比較的小さいk場合 (つまり、手元にある場合) は、単に a で既に選択されているインデックスを保存し、setそれらの 1 つにヒットした場合に新しいランダムな選択を行います。

編集:完全に異なるアプローチは、すべての順列を一度反復し、順列ごとに含めるかどうかを決定することです。順列の総数がnあり、それらを選択したい場合は、次のようにk書くことができます

selected = []
for i in xrange(n):
    perm = nextPermutation()
    if random.random() < float(k-len(selected))/(n-i):
        selected.append(perm)

kこれは、順列をランダムに正確に選択します。

于 2010-11-26T16:50:02.657 に答える
0

sample を使用して配列インデックスのリストを作成し、結果に従ってオブジェクトを生成できます。

def get_object(index):
    return MyClass(index)

またはこのようなもの。次に、 sample を使用して必要なインデックスを生成し、それらのインデックスでこの関数を呼び出します。

objs = map(get_object, random.sample(range(length), 0.001 * length))

これは、可能な配列インデックスのリストから選択するだけなので、少し間接的です。

于 2010-11-26T16:35:20.240 に答える
0

関数 createHugeArray() には、作成されるオブジェクトごとに 1 回繰り返されるコードが含まれていると思います。そして、オブジェクトはある種の初期値またはシードから生成されると推測しています。その場合、 createHugeArray() は次のようになります。

def createHugeArray( list_of_seeds ):
  huge_array = []                  
  for i in list_of_seeds:
    my_object = makeObject( i )
    huge_array.append( my_object )           
  return huge_array

(私は配列ではなくリストを使用しましたが、あなたはその考えを理解しています。)

オブジェクトを実際に作成する前にランダム サンプリングを行うには、乱数を生成する行を追加し、乱数が特定のしきい値を下回った場合にのみオブジェクトを作成します。1000 分の 1 のオブジェクトだけが必要だとします。random.randint(0,999) は 0 から 999 までの数値を与えるため、ゼロを取得した場合にのみオブジェクトを生成します。上記のコードは次のようになります。

import random

def createHugeArray( list_of_seeds ):
  huge_array = [] 

  for i in list_of_seeds:
    die_roll = random.randint(0,999)

    if( die_roll == 0 ):
      my_object = makeObject( i )
      huge_array.append( my_object ) 
  return huge_array

もちろん、あなたのコードがどのように機能するかについての私の推測が間違っている場合、これは役に立ちません。その場合は、申し訳ありませんが、幸運を祈ります:-)

于 2010-11-26T20:00:53.733 に答える
0

random.sample の仕組みを説明すると、

random.sample(container, k)コンテナからランダムに k 個の値を返します。ジェネレーターは、リスト、タプル、辞書内のキーまたは値のように反復可能であるため、コンテナーを反復処理してから、これらのランダムな要素を取得します。

たとえば、xrange ジェネレーターから 111 までの 4 つの乱数を意味するようrandom.sample(xrange(111),4)なものを返します。[33,52,111,1]k = 4

于 2010-11-26T16:36:27.840 に答える