Perl-хэш, когда и ключи, и значения являются ссылками на массив - PullRequest
5 голосов
/ 26 октября 2011

У меня проблема с отображением пар чисел на другие пары чисел.Например, (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.

Ответы [ 3 ]

10 голосов
/ 26 октября 2011

В 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 голосов
/ 26 октября 2011

Как и большинство вещей в 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];
0 голосов
/ 26 октября 2011

В итоге я использовал решение 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 "initializing\n";
    $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 Я бы добавил это как комментарийно это было слишком долго, и я подумал, что имеет смысл включить работающий пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...