Qiang Li
Qiang Li

Reputation: 10865

Create a Perl hash with an array as the key

How can I put an array (like the tuple in the following example) into a hash in Perl?

%h=();
@a=(1,1);
$h{@a}=1 or $h{\@a}=1??

I tried with an array reference, but it does not work. How do I to make it work? I want to essentially de-duplicate by doing the hashing (among other things with this).

Upvotes: 7

Views: 2299

Answers (3)

cdarke
cdarke

Reputation: 44434

I tried with array reference, but it does not work

Funny that, page 361 of the (new) Camel book has a paragraph title: References Don't Work As Hash Keys

So yes, you proved the Camel book right. It then goes on to tell you how to fix it, using Tie::RefHash.

I guess you should buy the book.

(By the way, (1,1) might be called a tuple in Python, but it is called a list in Perl).

Upvotes: 4

Paul Dixon
Paul Dixon

Reputation: 301125

Regular hashes can only have string keys, so you'd need to create some kind of hashing function for your arrays. A simple way would be to simply join your array elements, e.g.

$h{join('-', @a)} = \@a;  # A nice readable separator
$h{join($;, @a)} = \@a;   # A less likely, configurable separator ("\034")

But that approach (using a sentinel value) requires that you pick a character that won't be found in the keys. The following doesn't suffer from that problem:

$h{pack('(j/a*)*', @a)} = \@a;

Alternatively, check out Hash::MultiKey which can take a more complex key.

Upvotes: 11

stevenl
stevenl

Reputation: 6798

To remove duplicates in the array using hashes:

my %hash;
@hash{@array} = @array;
my @unique = keys %hash;

Alternatively, you can use map to create the hash:

my %hash = map {$_ => 1} @array;

Upvotes: 2

Related Questions