Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Как получить адрес ключа хэша?


Автор: loginn 22.3.2014, 13:28
Нужно хранить много сдлинных строк. Так же с каждой строкой должен быть ассоциирован глобальный и много разных локальных каунтеров.

Я думаю делать так:
1. Создать единый хэш для всех строк: %long_string и с каждой строкой будет ассоциирован глобальный каунтер.
2. Из других мест ссылаться на сам ключ, чтобы вести другие "локальные" каунтеры для этой строки. НО, тогда требуется хранить адрес самой строки, которая является ключом хэша. Адрес значения ключа получить легко: \$long_string{'STRING_1'} = 889. НО КАК получить адрес самой строки, которая является ключом в хэше (т.е. адрес 'STRING_1')? 

Делать так: $long_string{'STRING_1'} = (889, 'STRING_1') - не катит, т.к. строка будет дублироваться и память будет расходваться в 2 раза больше.


P.S. Заранее благодарю за ответ.

Автор: loginn 22.3.2014, 15:01
Т.е. суть вопроса можно переформулировать так:
#!/usr/bin/perl -w

$h{'str1'} = 1;
$h{'str2'} = 2;
$h{'str3'} = 3;
$h{'str4'} = 4;
$h{'str5'} = 5;


foreach (keys %h) {
  if ($_ eq 'str3') {
    $ref = \$_
  }
}

Можно ли получить адрес строки самого ключа без данного цикла? Чтобы при вставки новой строки в хэш не создавать заново массив ключей и не перебирать его в поисках данной строки, т.к. это достаточно накладно при большом количестве длинных строк.

Автор: Jimy 22.3.2014, 17:30
Перечитал 2 раза. В обоих сообщениях ты хочешь получить то, что изначально известно.
Цитата

Адрес значения ключа получить легко: \$long_string{'STRING_1'} = 889. НО КАК получить адрес самой строки, которая является ключом в хэше (т.е. адрес 'STRING_1')? 

Если получить значение легко, то ключ должно быть получить еще легче, разве нет? Он известен заранее и именно по нему получается значение из хэша.

Цитата

foreach (keys %h) {
  if ($_ eq 'str3') {
    $ref = \$_
  }
}
Можно ли получить адрес строки самого ключа без данного цикла?

Да, это 'str3'. И этот цикл не имеет смысла, его стоит заменить на
Код

$ref = \'str3';

Значение в $ref будет какое же как и при выполнении приведенного цикла.

Цитата

Чтобы при вставки новой строки в хэш не создавать заново массив ключей и не перебирать его в поисках данной строки

Код

if (!defined $h{'str3'}) {
...
}


Или имелось ввиду что-то другое?

Автор: loginn 22.3.2014, 21:19
Я понял Ваш ответ, но он немного о  другом.


Смотрите, допустим, $new_line = 'strinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstringstrinstring'

тогда мы делаем так: $h{$new_line} = 0;

теперь строка, которая была в $new_line была добавлена в хэш.

если я сделаю так: $ref = \$new_line, то рискую, что когда в $new_line окажется новая строка, то и $ref будет так же на нее указывать... а мне нужно, чтобы он указывал на саму строку, которая является ключом хэша.

А все потому, что строку эту нужно хранить только в одном месте, в том, где она хранится в качестве хэша. Но получить доступ к отдельному ключу хэша я не знаю как, кромt как ко всем сразу через keys %h.

Автор: loginn 22.3.2014, 21:48
насчет if (!defined $h{'str3'}) {
...
}
проверяет, присвоено ли что-либо ключу.

чтобы проверить есть ключ в хэше или нет, используется exists

Автор: Jimy 23.3.2014, 00:09
Цитата(loginn @ 22.3.2014,  21:19)
а мне нужно, чтобы он указывал на саму строку, которая является ключом хэша.

А все потому, что строку эту нужно хранить только в одном месте, в том, где она хранится в качестве хэша. Но получить доступ к отдельному ключу хэша я не знаю как, кромt как ко всем сразу через keys %h.

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

Автор: loginn 23.3.2014, 18:06
Т.е. вычислять SHA1/MD5 от строки, затем это значение использовать как ключ для вставки в хэш и с этим ключом ассоциировать строку, чтобы не потерять значение строки.
Но не слишком ли дорого будет на каждый лукап строки в хэше вычислять предварительно SHA1/MD5? 

ИМХО, не highload решение.

Автор: Jimy 23.3.2014, 18:51
Цитата(loginn @ 23.3.2014,  18:06)
Но не слишком ли дорого будет на каждый лукап строки в хэше вычислять предварительно SHA1/MD5? 

В вопросе не содержится достаточно информации, чтобы сказать будет это слишком дорого или не слишком. Из вопроса ясно, что критичным является перерасход памяти. Хэш строки, вероятно, занимает меньше места чем некая "длинная строка" из условия и поэтому позволяет экономить память.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)