Как получить доступ к случайному элементу в хэше Perl DBM? - PullRequest
1 голос
/ 28 января 2010

У меня есть хеш Perl DBM, содержащий список URL-адресов, которые я хочу выбрать случайным образом для балансировки нагрузки на сайтах. В результате я хочу выбрать ключ случайным образом или выбрать n-й элемент (чтобы я мог рандомизировать n).

Я знаю, что это противоречит концепции хэша, но возможно ли это?

ПРИМЕЧАНИЕ: пропущена ценная точка, поскольку размер хеша будет слишком большим, чтобы загрузить все ключи для случайного выбора.

Ответы [ 4 ]

3 голосов
/ 28 января 2010

Я не думаю, что какой-либо из пакетов DBM имеет API для получения случайного ключа или для получения ключей по номеру индекса. Вы можете найти конкретный ключ или прочитать все ключи в любом порядке, в котором база данных решит их вернуть (что может измениться, если база данных изменена, и может быть или не быть «случайным» достаточно для того, что вы хотите делать).

Вы можете прочитать все ключи и выбрать один, но для этого потребуется каждый раз читать всю базу данных (или, по крайней мере, значительную ее часть), и это, вероятно, слишком медленно.

Я думаю, вам нужно изменить структуру данных.

  1. Вы можете использовать реальную базу данных SQL (например, SQLite ), чтобы вы могли искать строки как последовательно номер строки и по URL. Это будет будь самым гибким.

  2. Вы можете использовать последовательное целое число в качестве ключа для вашего файла DBM. Тот сделает выбор случайным легко, но ты больше не можешь смотреть вверх записи по URL.

  3. Вы можете использовать два файла DBM: тот, который у вас есть сейчас, и второй, снабженный последовательным целым числом с URL-адресом в качестве значения. (На самом деле, поскольку URL-адреса не выглядят как целые числа, вы можете хранить оба набора записей в одном и том же файле DBM, но это усложнит любой код, использующий each.) Это потребует вдвое больше дискового пространства и приведет к вставке / удаление записей немного сложнее. Вам, вероятно, будет лучше с подходом № 1, если вы по какой-то причине не можете установить SQLite.

2 голосов
/ 28 января 2010

Выбор случайного элемента из массива проще, поэтому вы можете использовать keys(%foo) для получения массива ключей и случайного выбора из этого.

Я полагаю, что это вернет случайный элемент $x из массива:

$x = $array[rand @array];

Если вы хотите перемешать массив, рассмотрите List :: Util :: shuffle. См http://search.cpan.org/perldoc/List::Util#shuffle_LIST

1 голос
/ 28 января 2010

Вы можете использовать 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}};

С этим вы можете извлекать случайные значения по мере необходимости.

1 голос
/ 28 января 2010

Конечно, это возможно. Сначала получите список ключей. Затем рандомизируйте список, используя shuffle из List :: Util .

Затем зациклите клавиши.

Если ключей слишком много (поэтому хранить их все в списке и перемешать невозможно), просто помните, что вы используете связанные хеши. Просто используйте each для итерации по парам ключ-значение.

Порядок будет детерминированным, но AFAIK, он не будет алфавитным или порядок вставки. Это само по себе может дать вам то, что вы хотите.

...