Хэш Perl, когда и ключи, и значения являются ссылками на массив

#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. Поздравляю с решением. Когда вы сможете, пожалуйста, не забудьте пометить свой ответ как «принятый», чтобы другие могли извлечь уроки из вашего успеха. Приветствия ~