#perl #hash #reference
#perl #хэш #ссылка
Вопрос:
У меня проблема, когда пары чисел сопоставляются с другими парами чисел. Например, (1,2)->(12,97). Некоторые пары могут отображаться на несколько других пар, поэтому мне действительно нужна возможность отображения пары в список списков, например (1,2)->((12,97),(4,1)). В конце дня я хочу обработать каждое из значений (т. Е. Каждый список списков) отдельно.
В Python я мог бы сделать это, просто сказав:
key = ( x, y )
val = [ a, b ]
if (x,y) not in my_dict:
my_dict[ (x,y) ] = []
my_dict[ (x,y) ].append( [a,b] )
Однако в Perl я должен использовать ссылки для ключей и значений. Так что я, конечно, могу сказать:
$keyref = [ x1, y1 ]
$valref = [ a, b ]
%my_hash = { $keyref => $valref }
Но что происходит, когда появляется другая пара (x2, y2)? Даже если x2==x1 и y2==y1, $keyref=[x2,y2] будет отличаться от предыдущего сгенерированного keyref, поэтому я не вижу способа выполнить поиск. Конечно, я мог бы сравнить (x2, y2) с каждым разыменованным хэш-ключом, но, в конце концов, Бог дал нам хэш-таблицы именно для того, чтобы избежать необходимости делать это.
Существует ли решение на Perl?
Спасибо,
-W.
Комментарии:
1. Вы не можете использовать ссылку в качестве ключа. (по крайней мере, без использования связанного хэша)
Ответ №1:
В Perl все хэш-ключи являются строками или «строятся» перед поиском. Использование ссылки на массив в качестве ключа обычно является неправильным подходом.
Как насчет использования «двумерного» хэша?
$hash{$x1}{$y1} = [ $a, $b ];
# or
%hash = ( $x1 => { $y1 => [ $a, $b ] } );
($x2,$y2)=($x1,$y1);
print @{$hash{$x2}{$y2}}; # will print $a and $b
Ответ №2:
Как и большинство вещей в Perl, TMTOWTDI.
Вариант 1. используйте эмуляцию многомерного массива
$hash{$x,$y} = [$a, $b];
Смотрите также документацию для встроенной переменной $;
.
Вариант 2. используйте модуль Hash::MultiKey
tie %hash, 'Hash::MultiKey';
$hash{[$x, $y]} = [$a, $b];
Вариант 3. вместо этого используйте HoH (хэш хэшей)
$hash{$x}{$y} = [$a, $b];
Комментарии:
1. В итоге я использовал решение Socket Puppet (в виде вашего варианта 3). К вашему сведению, вот небольшой скрипт на Perl, который выполняет все операции, которые мне нужно выполнить в моем приложении. Печатные строки 2:, 3: и 4:,5: просто используют другой синтаксис для выполнения одних и тех же действий, а 0: и 1: были просто предназначены для проверки работоспособности на этом пути. Единственное, что это добавляет к этим примерам, — это использование массива массивов в качестве значения, которое идет вместе с ключами.
Ответ №3:
В итоге я использовал решение Socket Puppet (в форме варианта 3 Майкла Кармена). К вашему сведению, вот небольшой Perl-скрипт, который выполняет все операции, которые мне нужны в моем приложении.
Печатные строки 2:, 3: и 4:, 5: просто используют другой синтаксис для выполнения одного и того же, а строки 0: и 1: были просто предназначены для проверки работоспособности на этом пути.
Что это добавляет к предлагаемому решению, так это использование массива массивов в качестве значения, которое идет вместе с ключом.
@k1 = ( 12, 13 );
$aref = [ 11, 22 ];
$bref = [ 33, 44 ];
%h = {};
if( not exists $h{$k1[0]}{$k1[1]} ) {
print "initializingn";
$h{$k1[0]}{$k1[1]} = [];
}
push @{$h{$k1[0]}{$k1[1]}}, $aref;
push @{$h{$k1[0]}{$k1[1]}}, $bref;
print "0: ", join ':', @{$h{$k1[0]}{$k1[1]}}, "n";
print "1: ", join ':', ${$h{$k1[0]}{$k1[1]}}[0], "n";
print "2: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[0]}, "n";
print "3: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[1]}, "n";
print "4: ", join ':', @{$h{$k1[0]}{$k1[1]}->[0]}, "n";
print "5: ", join ':', @{$h{$k1[0]}{$k1[1]}->[1]}, "n";
PS Я бы добавил это в качестве комментария, но он был слишком длинным, и я подумал, что имеет смысл включить отработанный пример.
Комментарии:
1. Поздравляю с решением. Когда вы сможете, пожалуйста, не забудьте пометить свой ответ как «принятый», чтобы другие могли извлечь уроки из вашего успеха. Приветствия ~