Hashes

Hashes are key/value pairs

If you can look it up by name,you want a hash.The keys to a hash must be unique,but the values can be any scalar.

Sometimes you'll still see people call them "associative arrays",but don't think of them as arrays.

Create hashes as lists of key/value pairs

Create a hash with a list of key/value pairs.

  1. my %stooges = (
  2. 'Moe', 'Howard',
  3. 'Larry', 'Fine',
  4. 'Curly', 'Howard',
  5. 'Iggy', 'Pop',
  6. );

The => is a "fat comma", and is identical to a comma, plus it quotes the previous word:

  1. my %stooges = (
  2. Moe => 'Howard',
  3. Larry => 'Fine',
  4. Curly => 'Howard',
  5. Iggy => 'Pop',
  6. );

A hash in list context becomes a list of key/value pairs.

  1. my @hash_as_an_array = %stooges;
  2. # Contains ( 'Curly', 'Haward', 'Larry', 'Fine', etc... )

Just as the order of keys and values from a hash is effectively random, the order of the key/value pairs in a flattened hash is effectively random.

Access individual hash entries with squiggle braces

Get hash values with squiggly braces instead of square braces.

  1. print $stooges{'Iggy'};
  2. # Prints "Pop"

Set values that way, too.

  1. $stooges{'Shemp'} = 'Howard';

Overwrite existing values:

  1. $stooges{'Iggy'} = 'Ignatowski';

Delete an entry from the hash:

  1. delete $stooges{'Curly'};

Note that delete does not delete a file. unlink does that.

  1. unlink $stooges{'Moe'};
  2. # Deletes a file called 'Howard';

Get the keys/values of a hash

Use the keys and values keywords:

  1. my @stooge_first_names = keys %stooges;
  2.  
  3. my @stooge_last_names = values %stooges;

The order of the keys and values are guaranteed to match up to each other.

Hash keys autoquote words

If your hash key is a single word, you don't need quotes around it.

  1. $stooges{Curly} = 'Howard';

Hashes can only contain scalars

The values in a Perl hash may only be scalars. It is not possible to contain an array or a list in an array.

  1. $hash{comedians} = @stooges;
  2. # Assigns the length of @stooges to the value

If you want to store an array in a hash, you'll need to use references.

Hashes are unordered

The order of keys %hash and values %hash is effectively random. They will differ between runs of the program. It is not related to the order in which things were added.

You cannot "sort a hash"

The idea of "sorting a hash" does not exist in Perl, because hashes are unordered. You can sort the keys of a hash, or the values of a hash, as they are just lists.

Combine hashes with list assignment

To combine two hashes, look at them as lists and assign them to a hash.

  1. my %new_hash = (%hash1, %hash2);

The right-hand side of the equals is a long list of key/value pairs from both of the hashes. The list is then assigned to %new_hash. If any keys in %hash2 duplicate keys in %hash1, the %hash2 key/value pair take priority because they're assigned later.

When to use hash, when to use array

If you have things in a line, ordered, in a sequence, use an array.

  • A list of files to read
  • A list of people in a queue

If you have a bag of things, unordered, that you want to look up, use a hash.

  • An index of last names, looked up by first name
  • An index showing the size of files, looked up by name

To add (patches welcome!)

The difference between defined and exists

Use defined to see whether a hash element has a value other than undef. It will return true if the hash element has any value other than undef, even 0 and "" (the empty string), which evaluate to false.

Use exists to see whether a hash element has ever been initialized, even if it is not defined (i.e., it has the value 'undef').

  1. my %h;
  2. $h{'foo'} = undef;
  3.  
  4. defined $h{'foo'} ? print 1 : print 0;
  5. # $h{'foo'} is not defined, so it prints 0
  6. exists $h{'foo'} ? print 1 : print 0;
  7. # but it has been initialized nonetheless, and so this line prints 1

A hash element can be true only if it's defined. It can be defined only if it exists.

However, a hash element can exist without being defined. This means it will not return true even though it exists.

  1. if ( $h{'foo'} ) {
  2. print 'true';
  3. }
  4. else {
  5. print 'false';
  6. }
  7. # prints 'false'; since $h{'foo'} is not defined, it cannot be true

Access hash slices

Using exists & defined


Want to contribute?

Submit a PR to github.com/petdance/perl101