← Perl EnglishChapter 07 of 13

Hashes

## Learning Objectives - Create and manipulate hashes - Use hash functions (keys, values, each) - Check existence and delete entries - Work with hash slices - Understand hash internals ## Hash Basics ### Creating Hashes ```perl use strict; use warnings; my %empty; my %person = ( name => "Alice", age => 30, city => "Boston", ); # => is fat comma, quotes optional for valid identifiers ``` ### Accessing Elements ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); print $person{name}; # "Alice" print $person{age}; # 30 # Modify $person{age} = 31; $person{email} = "alice@example.com"; ``` ### Hash from Arrays ```perl my @keys = ("name", "age", "city"); my @values = ("Alice", 30, "Boston"); my %person = @keys; # Wrong! Creates (name, age, city, @values) my %person = (@keys, @values); # Correct ``` ### Hash from List ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); # Or using list directly my %data = ("key1", "value1", "key2", "value2"); ``` ## Hash Functions ### keys ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); my @k = keys %person; # ("name", "age", "city") # Iterate over keys foreach my $key (keys %person) { print "$key: $person{$key}\n"; } ``` ### values ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); my @v = values %person; # ("Alice", 30, "Boston") ``` ### each ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); while (my ($key, $value) = each %person) { print "$key => $value\n"; } ``` ### Iteration Order ```perl use strict; use warnings; my %nums = (one => 1, two => 2, three => 3); # Order not guaranteed (but consistent within program) foreach my $key (keys %nums) { print "$key => $nums{$key}\n"; } ``` ## Existence and Deletion ### exists ```perl my %person = ( name => "Alice", age => 30, ); if (exists $person{name}) { print "Name exists\n"; } if (!exists $person{email}) { print "No email\n"; } ``` ### delete ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); delete $person{age}; # Remove age print $person{age}; # undef # Safe delete delete $person{$_} for qw(name age city); ``` ### Defined Check ```perl my %person = ( name => "Alice", age => 30, email => undef, ); print defined $person{name}; # true print defined $person{email}; # false (even though key exists) print defined $person{nonexistent}; # false ``` ## Hash Size ```perl my %person = ( name => "Alice", age => 30, city => "Boston", ); my $count = scalar keys %person; # 3 print "Hash has $count entries\n"; # Empty check if (keys %person == 0) { print "Hash is empty\n"; } ``` ## Hash Sorting ### Sort by Keys ```perl my %scores = ( bob => 87, alice => 95, carol => 92, ); foreach my $name (sort keys %scores) { print "$name: $scores{$name}\n"; } ``` ### Sort by Values ```perl foreach my $name (sort { $scores{$a} <=> $scores{$b} } keys %scores) { print "$name: $scores{$name}\n"; } # Reverse order foreach my $name (sort { $scores{$b} <=> $scores{$a} } keys %scores) { print "$name: $scores{$name}\n"; } ``` ## Hash Slices ### Basic Slice ```perl my %person = ( first => "Alice", last => "Smith", age => 30, ); # Multiple access my ($first, $last) = @person{qw(first last)}; # Multiple assignment @person{qw(first, last)} = ("Bob", "Jones"); ``` ### Slice for Initialization ```perl my @fields = qw(name age city); my @vals = ("Alice", 30, "Boston"); my %person; @person{@fields} = @vals; ``` ## Hash References ### Creating References ```perl my %person = ( name => "Alice", age => 30, ); my $ref = \%person; # Access via reference print $ref->{name}; # "Alice" ``` ### Anonymous Hash ```perl my $person = { name => "Alice", age => 30, }; print $person->{name}; # "Alice" ``` ### Dereferencing ```perl my $ref = { a => 1, b => 2 }; my %hash = %$ref; # Or with braces if ambiguous my %hash = %{ $ref }; ``` ## Nested Hashes ```perl use strict; use warnings; my %company = ( engineering => { alice => { name => "Alice", title => "Engineer" }, bob => { name => "Bob", title => "Manager" }, }, sales => { carol => { name => "Carol", title => "Sales Rep" }, }, ); print $company{engineering}{alice}{title}; # "Engineer" # Reference style my $eng = $company{engineering}; print $eng->{alice}{name}; # "Alice" ``` ## Default Values ### Autovivification ```perl my %counts; $counts{apple}++; # Creates apple => 1 (not undef error) $counts{banana} += 5; # Creates banana => 5 # Without autovivification my %safe; if (exists $safe{key}) { $safe{key}++; } else { $safe{key} = 1; } ``` ### defined-or operator ```perl my %hash = (count => 0); $hash{count} //= 10; # Won't change (0 is defined) $hash{new} //= 10; # Sets new => 10 # vs || which uses truthiness $hash{count} ||= 10; # Would change 0 to 10! ``` ## Hash as Set ```perl # Using hash for unique values my %seen; my @unique; foreach my $item (@items) { if (!$seen{$item}++) { push @unique, $item; } } # Simple set operations my %set1 = map { $_ => 1 } qw(a b c); my %set2 = map { $_ => 1 } qw(b c d); # Union my %union = (%set1, %set2); # Intersection my @intersection = grep { $set1{$_} && $set2{$_} } (keys %set1, keys %set2); ``` ## Useful Hash Tricks ### Reversing Hash ```perl my %original = (a => 1, b => 2, c => 3); my %reversed = reverse %original; print "$reversed{1}\n"; # "a" ``` ### Counting Occurrences ```perl my @words = qw(apple banana apple cherry banana apple); my %count; foreach my $word (@words) { $count{$word}++; } print $count{apple}; # 3 ``` ### Inverting Hash ```perl my %正向 = (a => 1, b => 2, c => 3); my %反向 = reverse %正向; print "$反向{1}\n"; # "a" ``` ## Summary - Hashes created with `%` sigil and key-value pairs - Use `=>` (fat comma) for readability - `keys`, `values`, `each` for iteration - `exists` checks key existence - `delete` removes entry - Hash slices access multiple values - References use `->` for access - Hashes don't preserve order (pre 5.38) - Useful for counting, unique values, lookup tables

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →