読書とシャッフル配列には多くの不必要なデータの移動が含まれます。ここで
はいくつかのアイデアです:
ワン:あなたはランダムなサブセットを必要と言うとき、あなたはこの文脈では「ランダム」で正確に何を意味するのですか?つまり、レコードが特定の順序であるか、ランダム化しようとしているものと関連する順序ですか?
私の最初の考えは、レコードが関連する順序にない場合は、合計サイズをサンプルサイズで割って計算し、次にn番目のレコードを選択することによってランダムな選択を得ることができるということです。たとえば、5300万のレコードがあり、200万のサンプルが必要な場合は、5300万/ 200万~26の値を取るので、26レコードごとに読み取ります。
2:これで十分でない場合は、重複がないことを保証して、ゼロから5300万の範囲で200万の乱数を生成することがより厳密な解決策になります。
Two-A:サンプルサイズがレコードの総数に比べて小さかった場合、数百から数千を選んでいるような場合は、各エントリについて、前のすべてのエントリと比較して重複をチェックします。重複している場合は、周りを回り、ユニークな値が見つかるまで再度試してください。
Two-B:数字が単なる例ではなく実際の値であると仮定すると、サンプルサイズは総人口に比べて大きくなります。その場合、現代のコンピュータに十分なメモリがあれば、偽に初期化された5300万のブール値の配列を作成することで、効率的にこれを行うことができます。その後、200万回ループを実行します。反復ごとに、0から5300万の乱数を生成します。配列の対応するブール値を確認します。falseの場合はtrueに設定します。それが本当であれば、別の乱数を生成してやり直してください。
3つ:または、比較的大きな割合を考えれば、より良いアイデアはまだあります。含めるレコードの割合を計算します。次に、すべてのレコードのカウンタをループします。それぞれに対して、0から1までの乱数を生成し、それを所望の割合と比較する。それが少ない場合は、そのレコードを読んでサンプルに含める。それが大きい場合は、レコードをスキップします。
サンプルレコードの正確な数を取得することが重要な場合は、各レコードの割合を再計算できます。たとえば、例を単純にすると、100レコードのうち10レコードが必要です。
10/100 = .1で始めるので、乱数を生成します。 .04 < .1だから、私たちはレコード#1を含む。
ここで、パーセンテージを再計算します。私たちは残りの99のうち9つのレコードを残したい9/99〜= .0909私たちの乱数は.87です。それは大きいので、レコード#2はスキップします。
もう一度再計算してください。残りの98個のうち9個のレコードが必要です。だからマジックナンバーは9/98です。等
私たちが望むだけの数のレコードを取得すると、将来のレコードの確率はゼロになるので、決して進まないでしょう。終わり近くに十分なレコードを拾っていないと、確率は100%に非常に近くなります。同様に、まだ8つのレコードが必要で、8つのレコードしか残っていない場合、確率は8/8 = 100%になりますので、次のレコードを取得することが保証されます。
出典
2011-09-20 16:47:19
Jay
どうやって交換していますか? I/Oがボトルネックかシャッフルしていますか?おそらく、いくつかのコードも役に立ちます。 – delnan
@delnanリンクされたスレッドで説明されている両方の方法を試しました。 I/Oは間違いなく問題ありません。それはかなり素早くメモリにロードされますが、シャフリングのステップで*多くの時間を費やします。決して印刷を終了せずに印刷を開始します。今私はそれを試してみましたが、シャッフルアプローチがこのような多くの価値に対して十分に効率的になるとは思わないので、私はおそらく代替アプローチにもっと興味があります。 –
どのようにランダムにデータが必要ですか?ランダムな記号でジャンプし、重複を避けるために要素を検索した後、その要素を「使用済み」とマークするループを使用することができます。 –