スパイダー サイトの負荷を分散するためにランダムに選択する URL のリストを含む Perl DBM ハッシュがあります。その結果、キーをランダムに選択するか、n 番目の要素を選択したい (n をランダム化できるようにするため)。
これがハッシュの概念に反することは承知していますが、これは可能ですか?
注: ハッシュ サイズが大きすぎてすべてのキーを読み込んでランダムに選択できないという重要な点を見逃していました。
どの DBM パッケージにも、ランダム キーを取得するための API や、インデックス番号でキーを取得するための API はないと思います。特定のキーを検索するか、データベースがそれらを返すために選択した順序ですべてのキーを読み取ることができます (データベースが変更されると変更される可能性があり、必要なものに対して十分に「ランダム」である場合とそうでない場合があります)する)。
すべてのキーを読み取って 1 つを選択することもできますが、毎回データベース全体 (または少なくともかなりの部分) を読み取る必要があり、おそらく遅すぎます。
データ構造を再編成する必要があると思います。
実際の SQL データベース ( SQLiteなど) を使用できるため、連続した行番号と URL の両方で行を検索できます。これが最も柔軟になります。
DBM ファイルのキーとして連続する整数を使用できます。これにより、ランダムなエントリを簡単に選択できますが、URL でエントリを検索することはできなくなりました。
2 つの DBM ファイルを使用できます。1 つは現在持っているもので、もう 1 つは URL を値として連続整数でキー付けされたものです。(実際には、URL は整数のように見えないため、両方のレコードのセットを同じ DBM ファイルに保存できますが、each
.もう少し複雑です。何らかの理由で SQLite をインストールできない場合を除き、おそらくアプローチ #1 を使用した方がよいでしょう。
配列からランダムな要素を選択する方が簡単なので、 を使用keys(%foo)
してキーの配列を取得し、そこからランダムに選択できます。
これは配列からランダムな要素を返すと思います$x
:
$x = $array[rand @array];
配列をシャッフルしたい場合は、List::Util::shuffle を検討してください。http://search.cpan.org/perldoc/List::Util#shuffle_LISTを参照してください
もちろん可能です。まず、キーのリストを取得します。shuffle
次に、 from List::Utilを使用して、リストをランダム化します。
次に、キーをループします。
キーが多すぎる場合 (そのため、すべてをリストに保持してシャッフルすることはできません)、Tie ハッシュを使用していることに注意してください。each
キーと値のペアを反復処理するために使用します。
順序は決定論的ですが、知る限り、アルファベット順または挿入順ではありません。それ自体で、あなたが望むものを手に入れることができるかもしれません。
データを保持するために、従来の DB ファイルの代わりにDBM::Deepを使用できます。
tie %hash, "DBM::Deep", {
file => "foo.db",
locking => 1,
autoflush => 1
};
# $hash{keys} = [ ... ]
# $hash{urls} = { ... } <- same as your current DB file.
my $like_old = $hash{urls}; # a ref to a hash you can use like your old hashref.
my $count = @{$hash{keys}};
これにより、必要に応じてランダムな値を引き出すことができます。