7

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).

6
  • you will need to devise your own hashing algorithm for your array, and then use that as your key. Commented Jun 13, 2013 at 7:14
  • can you give an example please? Commented Jun 13, 2013 at 7:15
  • This isn't possible: All keys have to be strings. You can however join the parts of the array to form a key with a character you can guarantee won't appear in the values. This could be a NUL byte: $h{join "\x00", @a} = 1. Commented Jun 13, 2013 at 7:15
  • 1
    @mpapec This is ancient multidimensional array emulation (from before there were references in the language). The items are joined by $; to form a key. This is not to be encouraged. See perlvar for a description. Commented Jun 13, 2013 at 9:27
  • 1
    @mpapec: It is the default value for $; - the subscript separator. The value was chosen because it is the same as AWK uses for SUBSEP. Read about it in perlvar. Commented Jun 13, 2013 at 9:27

3 Answers 3

11

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.

Sign up to request clarification or add additional context in comments.

Comments

4

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).

Comments

2

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;

3 Comments

-1: Doesn't address the OP's inability to use a non-scalar value as a hash key.
I beg to differ. It deals with his real question (at the end of the post) which is to use a hash to dedup an array. That suggests to me that what he's trying to achieve by setting an array as a hashkey is to assign each of the elements in the array as a separate key in the hash.
Agreed that it shows how to dedup a data set using a hash, but my reading of the question is that the data elements in the set are tuples, not the elements of each tuple. So, if he can't use the tuples as keys, then using keys to dedup isn't possible. Perhaps OP can clarify what exactly he's deduping?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.