これは本質的に、この質問のより制約されたバージョンです。
多数の行を含む非常に大きなテキストファイルがあるとします。
一定の確率でファイルからランダムに行を選択する必要がありますが、制約があります。
- これはソフトリアルタイムアプリケーションであるため、ファイル全体を反復処理することはできません。選択には一定の時間がかかるはずです。
- メモリの制約により、ファイルをキャッシュできません。
- ファイルは実行時に変更できるため、ファイルの長さを一定と見なすことはできません。
私の最初の考えは、lstat()
呼び出しを使用して合計ファイルサイズをバイト単位で取得することです。fseek()
次に、ランダムなバイトオフセットに直接アクセスするために使用でき、ファイルのランダムな部分へのO(1)アクセスのようなものを取得します。
問題は、次の改行を読んでそれを1日と呼ぶようなことはできないということです。これは、長い行に偏った分布が生成されるためです。
この問題を解決するための私の最初の考えは、最初の「n」の改行(必要に応じてファイルの先頭に折り返す)まで読み、次にこの小さいセットから均一な確率で行を選択することです。ファイルの内容はランダムに並べられていると考えるのが安全です。したがって、このサブサンプルは長さに関して均一である必要があります。また、開始点はすべての可能な点から均一に選択されているため、ファイルからの均一な選択を次のように表す必要があります。全体。したがって、疑似Cでは、アルゴリズムは次のようになります。
lstat(filepath, &filestat);
fseek(file, (int)(filestat.off_t*drand48()), SEEK_SET);
char sample[n][BUFSIZ];
for(int i=0;i<n;i++)
fgets(sample[i], BUFSIZ, file); //plus some stuff to deal with file wrap around...
return sample[(int)(n*drand48())];
これは特にエレガントな解決策のようには思えませんし、均一になるとは完全には確信していません。そのため、もっと良い方法があるのではないかと思います。何かご意見は?
編集:さらに検討すると、開始点は長い単語の中にある可能性が高く、したがって均一ではないため、私の方法は均一ではないと確信しています。トリッキー!