Hashes

6.1 Creating and Accessing Hashes

use v5.36;
my %age = (
    alice => 30,           # fat comma auto-quotes simple keys
    bob   => 25,
    'mary-jane' => 41,     # quote keys with special characters
);

say $age{alice};           # 30 (a single element is a scalar: $)
$age{carol} = 35;          # add or update
delete $age{bob};          # remove a key
say exists $age{bob} ? 'yes' : 'no';
say scalar keys %age;      # number of keys
my @names  = keys %age;    # order is pseudo-random!
my @values = values %age;
my @two    = @age{qw(alice carol)};   # hash slice: (30, 35)
my %subset = %age{qw(alice carol)};   # key/value slice (5.20+)
my %inverse = reverse %age;           # swap keys and values (values must be unique)
%age = ();                            # clear

6.2 Iterating

for my $name (sort keys %age) {
    say "$name is $age{$name}";
}
while (my ($k, $v) = each %age) {      # don't modify the hash while using each
    say "$k => $v";
}
for my ($k, $v) (%age) {               # multi-variable foreach (5.36+)
    say "$k: $v";
}
for my $name (sort { $age{$a} <=> $age{$b} } keys %age) {   # sort by value
    say "$name: $age{$name}";
}

6.3 Common Hash Idioms

Hash keys are always strings. Hash order is intentionally randomized (for security), so sort keys when order matters, or use Hash::Ordered / Tie::IxHash.

# Counting
my %count;
$count{$_}++ for qw(a b a c a b);           # (a => 3, b => 2, c => 1)

# Unique values (preserving order)
my %seen;
my @unique = grep { !$seen{$_}++ } qw(x y x z y);

# Lookup table / set
my %valid = map { $_ => 1 } qw(red green blue);
say 'valid' if $valid{green};

# Default values
my %opts = (verbose => 0, color => 'auto', %user_opts);   # later keys override earlier ones

# Grouping
my %by_len;
push @{ $by_len{length $_} }, $_ for qw(a bb cc ddd);     # autovivification