Hash Maps
A hash map (also called a dictionary or associative array) stores key/value pairs and offers fast insert, look-up, and iteration. The three core operations shown here are inserting a pair, looking a key up safely (handling the absent case), and iterating over every entry.
sub main() {
%ages = {"ada": 36, "alan": 41}
%all = %ages.set("grace", 45)
match %all.get("ada") {
Some($a) { print("ada is $a") }
None { print("ada is unknown") }
}
$has = %all.has_key("alan")
print("has alan: $has")
for $name, $age in %all {
print("$name -> $age")
}
$n = %all.keys().count()
print("count: $n")
}A map binding carries the % sigil and is indexed with braces: %all{"ada"}. Because bindings are immutable by default, set returns a fresh map rather than mutating in place, so the result is bound to a new name. get returns Option[V], forcing the absent case to be handled with match, and a map for loop binds two variables, key then value.
package main
import (
"fmt"
"sort"
)
func main() {
ages := map[string]int{"ada": 36, "alan": 41}
ages["grace"] = 45 // insert
if a, ok := ages["ada"]; ok { // look up
fmt.Println("ada is", a)
}
_, has := ages["alan"]
fmt.Println("has alan:", has)
keys := make([]string, 0, len(ages))
for k := range ages {
keys = append(keys, k)
}
sort.Strings(keys)
for _, name := range keys { // iterate
fmt.Printf("%s -> %d\n", name, ages[name])
}
fmt.Println("count:", len(ages))
}
Go's built-in map[K]V is created with a literal and assigned to directly. The two-value index form a, ok := ages["ada"] distinguishes a present key from a missing one, since a bare read returns the zero value. Iteration order over a map is deliberately randomized, so the keys are collected and sorted first for stable output.
let () =
let ages = Hashtbl.create 16 in
Hashtbl.replace ages "ada" 36;
Hashtbl.replace ages "alan" 41;
Hashtbl.replace ages "grace" 45; (* insert *)
(match Hashtbl.find_opt ages "ada" with (* look up *)
| Some a -> Printf.printf "ada is %d\n" a
| None -> print_endline "ada is unknown");
Printf.printf "has alan: %b\n" (Hashtbl.mem ages "alan");
let pairs = Hashtbl.fold (fun k v acc -> (k, v) :: acc) ages [] in
List.iter (fun (k, v) -> Printf.printf "%s -> %d\n" k v)
(List.sort compare pairs); (* iterate *)
Printf.printf "count: %d\n" (Hashtbl.length ages)
The standard Hashtbl module provides a mutable hash table; replace inserts or overwrites a binding. find_opt returns 'a option, so the missing case is handled explicitly with a match rather than raising Not_found. Hashtbl.fold collects every pair into a list, which is sorted for deterministic iteration.
import qualified Data.Map as Map
import Data.Map (Map)
main :: IO ()
main = do
let ages0 = Map.fromList [("ada", 36), ("alan", 41)] :: Map String Int
ages = Map.insert "grace" 45 ages0 -- insert
case Map.lookup "ada" ages of -- look up
Just a -> putStrLn ("ada is " ++ show a)
Nothing -> putStrLn "ada is unknown"
putStrLn ("has alan: " ++ show (Map.member "alan" ages))
mapM_ (\(k, v) -> putStrLn (k ++ " -> " ++ show v))
(Map.toList ages) -- iterate, key-ordered
putStrLn ("count: " ++ show (Map.size ages))
Data.Map is an immutable, balanced-tree map, so insert returns a new map sharing structure with the old one rather than mutating. lookup returns Maybe v, and the Just/Nothing cases are matched directly. Map.toList yields the pairs already sorted by key, which suits the lazy, pure style.
use strict;
use warnings;
my %ages = (ada => 36, alan => 41);
$ages{grace} = 45; # insert
print "ada is ", ($ages{ada} // "unknown"), "\n"; # look up
print "has alan: ", (exists $ages{alan} ? "true" : "false"), "\n";
for my $name (sort keys %ages) { # iterate
print "$name -> $ages{$name}\n";
}
print "count: ", scalar(keys %ages), "\n";
A %hash is Perl's native associative array; a single element is reached with the $ages{key} scalar form. The defined-or operator // supplies a default for an absent key, while exists tests membership without autovivifying. keys is sorted so iteration order is stable.
my %ages = ada => 36, alan => 41;
%ages<grace> = 45; # insert
say "ada is ", %ages<ada> // "unknown"; # look up
say "has alan: ", %ages<alan>:exists;
for %ages.keys.sort -> $name { # iterate
say "$name -> %ages{$name}";
}
say "count: ", %ages.elems;
Raku hashes use the % sigil and the angle-bracket %ages<key> shortcut for string subscripts. The :exists adverb tests for a key, and // provides a default when a value is missing. .keys, .sort, and .elems are methods on the hash, and string interpolation reaches an element inline with %ages{$name}.
use std::collections::HashMap;
fn main() {
let mut ages: HashMap<&str, i32> = HashMap::new();
ages.insert("ada", 36);
ages.insert("alan", 41);
ages.insert("grace", 45); // insert
match ages.get("ada") { // look up
Some(a) => println!("ada is {a}"),
None => println!("ada is unknown"),
}
println!("has alan: {}", ages.contains_key("alan"));
let mut pairs: Vec<_> = ages.iter().collect();
pairs.sort_by_key(|&(k, _)| *k);
for (name, age) in pairs { // iterate
println!("{name} -> {age}");
}
println!("count: {}", ages.len());
}
std::collections::HashMap needs a mut binding because insert mutates in place. get returns Option<&V>, so the missing case is handled with match rather than a panic, and contains_key tests membership. Iteration order is unspecified, so the pairs are collected into a Vec and sorted by key before printing.
ages = {"ada": 36, "alan": 41}
ages["grace"] = 45 # insert
print("ada is", ages.get("ada", "unknown")) # look up
print("has alan:", "alan" in ages)
for name, age in ages.items(): # iterate
print(f"{name} -> {age}")
print("count:", len(ages))
The built-in dict is Python's hash map; a key is set with ages[key] = value. .get(key, default) looks a key up without raising KeyError, and the in operator tests membership. .items() yields key/value pairs for iteration, and since Python 3.7 a dict preserves insertion order.