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:
%authors_books = (Hashes can also be defined in other ways. However, I prefer this way: clean and readable.
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath',
'Ernest Hemingway' => 'The Old Man and the Sea' );
%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);
%copy_authors_books = %authors_books;To make a partial copy:
%partial_copy_authors_books = %authors_books{'Scott Fitzgerald', 'John Steinbeck'};
%copy_authors_books = ();
print($authors_books{'John Steinbeck'} . "\n");Notice the curly braces: $authors_books{'Ernest Hemingway'}.# notice the $
print("The best book of Hemingway is '" . $authors_books{'Ernest Hemingway'} . "'\n");
print("@authors_books{'Scott Fitzgerald', 'John Steinbeck'}");Notice the use of @# output: The Great Gatsby The Grapes of Wrath
@keys = keys(%authors_books);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:# notice the @
print("Keys of the hash %authors_books are: @keys\n");
@keys = sort(keys(%authors_books));Study Chapter 1.5.4 on Sort.
print("Keys of the hash %authors_books are: @keys\n");
$no_elements = keys(%authors_books);
foreach $author (keys(%authors_books)) {You could also iterate over the values of a hash:
print("$author => $authors_books{$author}\n");# or: print($author . " => " . $authors_books{$author} . "\n");
}
foreach $title (values(%authors_books)) {In the Exit section, I'll show you how to use an alternative way with 'each'.
print($title ."\n");
}
%copy_authors_books = %authors_books;You can also use a hash-slice:
$copy_authors_books{'Herman Melville'} = 'Moby-Dick';
%copy_authors_books = ();Notice that adding a new member with an existing key will overwrite the old member. Unique keys is one of the niceties of hashes.
@copy_authors_books{'Scott Fitzgerald', 'John Steinbeck'} = ('Tender Is the Night', 'East of Eden');
%copy_authors_books = %authors_books;Better (check first if the element exists):
delete($copy_authors_books{'John Steinbeck'});
%copy_authors_books = %authors_books;Or (check with exists):
delete($copy_authors_books{'John Steinbeck'}) if ($copy_authors_books{'John Steinbeck'})
%copy_authors_books = %authors_books;
delete($copy_authors_books{'John Steinbeck'}) if (exists $copy_authors_books{'John Steinbeck'})
%copy_authors_books = %authors_books;Chapter 1.5.5 shows how to change multiple values with 'foreach'.
$copy_authors_books{'Herman Melville'} = 'Pierre';
@keys = sort(keys(%authors_books) );Also possible:
print("Keys of the hash %authors_books are: @keys\n");
@keys = reverse ( sort(keys(%authors_books) );For sorting hashes via possibly not unique values, you need a specific sort-function (low to high):
print("Keys of the hash %authors_books are: @keys\n");
%students_math_test = (To sort in a reverse order (high to low), change the position $a and $b in the sort-function 'sort_values':
'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");
}
sub sort_values {The variables $a and $b are built-in, so do not give them your own variablenames.
return $students_math_test{$b} <=> $students_math_test{$a}
}
%students_math_test = (
'Student_1' => '6.1',
'Student_2' => '7.3',
'Student_3' => '9.2' );
$sum = 0;I want to add 0.2 to the test scores:
$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
foreach $score (values(%students_math_test)) {Now the hash has modified values!
$score += 0.2;
}
%students_math_test = (
'Student_1' => '6.3',
'Student_2' => '7.5',
'Student_3' => '9.4' );
%authors_books = (You can also use the shorter 'while' construct:
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath',
'Ernest Hemingway' => 'The Old Man and the Sea' );
$no_elements = keys(%authors_books);
for ($i = 0; $i < $no_elements; $i++) {
($author, $book_title) = each (%authors_books);
print($author . " " . $book_title . "\n");
};
while (($author, $book_title) = each (%authors_books)) {;In both solutions, you've no control over the order of the hash members.
print($author . " " . $book_title . "\n");
};
while ($author = each (%authors_books)) {;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).
print($author . " " . $authors_books{$author} . "\n");
};