tags:

views:

103

answers:

4

Consider the following:

use strict;
use Data::Dumper;
my $hash={['one','two']=>[1,2]};
print Dumper($hash);
=for comment
prints....
$VAR1 = {
          'ARRAY(0x35358)' => [
                               1,
                               2
                              ]
         };
=cut

As an alternative, the key in the hash can be constrcuted as "one\ttwo" and then I can separate out the elements of the key based on tab delimiter (in latter part of the program while munging the data).

Any advice on how to store the key as a array reference?

+3  A: 

Hash::MultiKey

daxim
A: 

You can serialize the data structure (e.g. with Data::Dumper or other similar tool) and use the string as a hash key:

my $hash = {
    Dumper(['one','two']) => [1,2],
};

Eval the key to get the data structure back.

eugene y
I'm having trouble understanding how it works. Can you add an explanation? In particular, how can I check "Does the hash contain X, Y"? In the alternative version which I mentioned in the question itself, I could do my $search_key="X"."\t"."Y"; if(exists($hash->{$search_key})) –
Sachin
my $search_key = Dumper( ['X', 'Y'] );
MkV
@Sachin: `my $search_key = Dumper( ['X', 'Y'] ); if (exists $hash->{$search_key}) {...}`. See also man Data::Dumper for some ways to format the output of the Dumper() function.
eugene y
+5  A: 

No, a normal (non-tied) Perl hash can only have strings as keys. Anything else - arrayrefs, objects, whatever - will be stringified if used as a hash key, which leaves the hash key unusable as whatever non-string thing you originally had.

Hash::MultiKey uses the magic of tie to sidestep this restriction.

Dave Sherohman
You can use a (stringified) reference as a hash key, but not everything that *can* be done *should* be done.
Ether
+1  A: 

What is the need here? Why would you be looking up a hash element by an array? It seems a case for a HoH, like:

use strict;
use warnings;
use Data::Dumper;
my $hash = { one => { two => [1,2] } };
print Dumper($hash);

prints

$VAR1 = {
          'one' => {
                     'two' => [
                                1,
                                2
                              ]
                   }
        };

especially since you will be splitting the array back into its elements later. To check for existence something like:

if (exists($hash->{one}) && exists($hash->{one}{two}))

the && is needed as

if (exists($hash->{one}{two}))

would autovivify $hash->{one} if it didn't exist.

MkV
But if I have more (than two) elements constituting the key then if(exists()) will be too long to read.
Sachin
and the answer to the question?
MkV
MkV
You'll need 'reduce' from List::Util, it is a core module. @array is ('one', 'two') or ('X', 'Y') or whatever. You could put this, or another function using nested exists tests in a function which takes $hash and @array as parameters
MkV