3

内容のファイルがあります

abc
def
high
lmn
...
...

ファイルには 200 万行を超える行があります。ファイルから行をランダムにサンプリングし、50K 行を出力したいと考えています。この問題にアプローチする方法について何か考えはありますか? 私は、Perl とその機能の方針に沿って考えていましたrand(または、便利なシェル コマンドが適切でしょう)。

関連する (おそらく重複する) 質問:

4

5 に答える 5

12

基本的にすべての行の約2.5%を出力したい場合、これは次のようになります。

print if 0.025 > rand while <$input>;
于 2009-06-23T20:03:34.033 に答える
5

シェルウェイ:

sort -R file | head -n 50000
于 2009-06-23T20:05:35.387 に答える
3

perlfaq5から:「ファイルからランダムな行を選択するにはどうすればよいですか?」


ファイルをデータベースにロードしたり、ファイル内の行に事前にインデックスを付けたりする以外に、実行できることがいくつかあります。

CamelBookのリザーバーサンプリングアルゴリズムは次のとおりです。

srand;
rand($.) < 1 && ($line = $_) while <>;

これは、ファイル全体を読み込むよりもスペースに大きな利点があります。この方法の証明は、DonaldE.KnuthによるTheArtof Computer Programming 、Volume 2、Section3.4.2にあります。

そのアルゴリズムの関数を提供するFile::Randomモジュールを使用できます。

use File::Random qw/random_line/;
my $line = random_line($filename);

もう1つの方法は、ファイル全体を配列として扱うTie::Fileモジュールを使用することです。ランダムな配列要素にアクセスするだけです。

于 2009-06-24T17:09:19.090 に答える
2

正確な数の行を抽出する必要がある場合:

use strict;
use warnings;

# Number of lines to pick and file to pick from
# Error checking omitted!
my ($pick, $file) = @ARGV;

open(my $fh, '<', $file)
    or die "Can't read file '$file' [$!]\n";

# count lines in file
my ($lines, $buffer);
while (sysread $fh, $buffer, 4096) {
    $lines += ($buffer =~ tr/\n//);
}

# limit number of lines to pick to number of lines in file
$pick = $lines if $pick > $lines;

# build list of N lines to pick, use a hash to prevent picking the
# same line multiple times
my %picked;
for (1 .. $pick) {
    my $n = int(rand($lines)) + 1;
    redo if $picked{$n}++
}

# loop over file extracting selected lines
seek($fh, 0, 0);
while (<$fh>) {
    print if $picked{$.};
}
close $fh;
于 2009-06-23T20:23:57.173 に答える
2

パールの方法:

CPAN を使用します。必要なことを正確に行うモジュールFile::RandomLineがあります。

于 2009-06-23T20:44:05.747 に答える