1. Hash

A hash is data structure that stores one or more key/value pairs. Variables whose names begin with % are hashes, also called associative arrays. The variable %color is a hash, which is different from $color, though members of %color are selected by $color{$key}.
Two remarks:

  1. The keys of a hash, as well as their associated values, are scalars and have to be unique (which is not required for values).
  2. Hashes are unsorted (so, push and pop functions make no sense).
Why a hash? A hash is a compact data structure, i.e. it can result in more concise code than when using an array.

1.1 Create

1.1.1 Create a named hash
The next hash with the name 'authors_books' contains the name of an author as a key and an authors book title as a value:

%authors_books = (
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath',
'Ernest Hemingway' => 'The Old Man and the Sea' );
Hashes can also be defined in other ways. However, I prefer this way: clean and readable.

Recommendation:
use always quotes around the keys and values.
1.1.2 Merge hashes

%authors_books_1 = (
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath' );

%authors_books_2 = (
'Ernest Hemingway' => 'The Old Man and the Sea',
'Mark Twain' => 'The Adventures of Huckleberry Finn' );

%combined_hash_authors_books = (%authors_books_1, %authors_books_2);
1.1.3 Copy a hash
To make a full copy:

%copy_authors_books = %authors_books;
To make a partial copy:

%partial_copy_authors_books = %authors_books{'Scott Fitzgerald', 'John Steinbeck'};
1.1.4 Empty a hash

%copy_authors_books = ();

1.2 Access

1.2.1 Access hash elements
Accessing the members of the hash:

print($authors_books{'John Steinbeck'} . "\n"); # notice the $
print("The best book of Hemingway is '" . $authors_books{'Ernest Hemingway'} . "'\n");
Notice the curly braces: $authors_books{'Ernest Hemingway'}.
1.2.2 Hash-slices

print("@authors_books{'Scott Fitzgerald', 'John Steinbeck'}"); # output: The Great Gatsby The Grapes of Wrath
Notice the use of @

1.3 Print

To print the keys:

@keys = keys(%authors_books); # notice the @
print("Keys of the hash %authors_books are: @keys\n");
Notice that you've -if you run this many times- again and again different results, i.e. the order of the key/value pair is not according your hash definition AND has different order. To avoid this problem, use sort:

@keys = sort(keys(%authors_books));
print("Keys of the hash %authors_books are: @keys\n");
Study Chapter 1.5.4 on Sort.

1.4 Iterate

1.4.1. Number of hash members

$no_elements = keys(%authors_books);
1.4.2. Iterate with 'foreach'
There are a few ways to iterate over a hash. The recommended way is to use 'foreach'.

To print the keys and the values on separate lines:

foreach $author (keys(%authors_books)) {
print("$author => $authors_books{$author}\n"); # or: print($author . " => " . $authors_books{$author} . "\n");
}
You could also iterate over the values of a hash:

foreach $title (values(%authors_books)) {
print($title ."\n");
}
1.4.3. Iterate with 'while'
Peter Meszaros wrote a nice solution to the The Perl Weekly Challenge task 246 using 'while'.

'Write a script that outputs six unique random integers from the range 1 to 49'

sub six_outof_fortynine
{
    my %h;

    while (keys %h < 6) { nicely done!
        $h{int(rand(48))+1}++;
    }
    return sort {$a <=> $b} keys %h;
}

for my $i (1..10) {
    printf "%2d %s\n", $i, join('-', map { sprintf("%2d", $_) } six_outof_fortynine());
}
1.4.4 Practical example

$str = "reinier";
%count = ();

foreach $char (split(//, $str)) {
  $count{$char}++;
}	

foreach $key (keys(%count)) {
  print("$key => $count{$key}\n");  # Output: i => 2 n => 1 e => 2 r => 2
}

1.5 Operate

1.5.1 Add an element to a hash
Adding a new member to the hash is straightforward:

%copy_authors_books = %authors_books;
$copy_authors_books{'Herman Melville'} = 'Moby-Dick';
You can also use a hash-slice:

%copy_authors_books = ();
@copy_authors_books{'Scott Fitzgerald', 'John Steinbeck'} = ('Tender Is the Night', 'East of Eden');
Notice that adding a new member with an existing key will overwrite the old member. Unique keys is one of the niceties of hashes.
1.5.2 Remove an element of a hash with 'delete'
To remove a single element of a hash, you can use -if you know its key- 'delete':

%copy_authors_books = %authors_books;
delete($copy_authors_books{'John Steinbeck'});
Better (check first if the element exists):

%copy_authors_books = %authors_books;
delete($copy_authors_books{'John Steinbeck'}) if ($copy_authors_books{'John Steinbeck'})
Or (check with exists):

%copy_authors_books = %authors_books;
delete($copy_authors_books{'John Steinbeck'}) if (exists $copy_authors_books{'John Steinbeck'})
1.5.3 Update a hash element
An hash element can be updated simply by assigning a new value to a value:

%copy_authors_books = %authors_books;
$copy_authors_books{'Herman Melville'} = 'Pierre';
Chapter 1.5.5 shows how to change multiple values with 'foreach'.
1.5.4 Sort
Sorting hashes via the unique keys is common:

@keys = sort(keys(%authors_books) );
print("Keys of the hash %authors_books are: @keys\n");
Also possible:
@keys = reverse ( sort(keys(%authors_books) );
print("Keys of the hash %authors_books are: @keys\n");
For sorting hashes via possibly not unique values, you need a specific sort-function (low to high):

%students_math_test = (
'Student_1' => '6.1',
'Student_2' => '4.3',
'Student_3' => '6.1',
'Student_4' => '7.2' );

sub sort_values {
return $students_math_test{$a} <=> $students_math_test{$b}
}

foreach $student (sort sort_values keys(%students_math_test)) {
print($student . " " . $students_math_test{$student} . "\n");
}
To sort in a reverse order (high to low), change the position $a and $b in the sort-function 'sort_values':

sub sort_values {
return $students_math_test{$b} <=> $students_math_test{$a}
}
The variables $a and $b are built-in, so do not give them your own variablenames.

1.5.5 Again: iterating over a hash, using and modifying values
Pars pro toto, here the results of three students on a math test. First, I'll determine the average.

%students_math_test = (
'Student_1' => '6.1',
'Student_2' => '7.3',
'Student_3' => '9.2' );

$sum = 0;
$count = 0;
foreach $score (values(%students_math_test)) {
$sum += $score;
$count++;
}
$average = $sum/$count;
print($average . "\n"); # result: 7.53333333333333
printf("%.1f\n", $average); # result: 7.5
I want to add 0.2 to the test scores:

foreach $score (values(%students_math_test)) {
$score += 0.2;
}
Now the hash has modified values!

%students_math_test = (
'Student_1' => '6.3',
'Student_2' => '7.5',
'Student_3' => '9.4' );
Notice that I do not recommend to use 'each': while running a hash programm, unexpected behaviour will arise when you change the hash (adding or deleting hash members).

'foreach' does not have these problems, so it is safe use always 'foreach' instead of 'each'.

Exit: conversions

1. Convert list to hash

%hash = ();
@list = ('a'..'d');
$id = 0;
foreach $value (@list) {

 $id++;
 $hash{"key_" . $id} = $value;
	
}

foreach $key ( sort( keys(%hash) ) ) {
 print("$key => $hash{$key}\n");
}		

Output:
key_1 => a
key_2 => b
key_3 => c
key_4 => d
2. Convert values hash to list

@list = ();
%hash = (
 key_1 => 'a',
 key_2 => 'b',
 key_3 => 'c',
 key_4 => 'd'
);

@list = sort( values(%hash) );

print("@list\n"); # Output: a b c d 
3. Convert keys hash to string

%hash = (
 key_1 => 'a',
 key_2 => 'b',
 key_3 => 'c',
 key_4 => 'd'
);

$mc_keys = join(', ', sort( keys(%hash) ) );

print("$mc_keys\n"); # Output: key_1, key_2, key_3, key_4
To make a list of strings:

%hash = (
 key_1 => 'a',
 key_2 => 'b',
 key_3 => 'c',
 key_4 => 'd'
);

@arr = map {"[ $_: " . uc($hash{$_}) . " ]"} sort(keys(%hash));
print("@arr\n"); # Output: [ key_1: A ] [ key_2: B ] [ key_3: C ] [ key_4: D ]