Docs/Language basics

Maps

Look up values by key.

On this page

Map[T] stores values by String key. HashMap[K, V] does the same for other key types.

Create and update a map#

Valk
fn main() {
    let stock = Map[int]{ "notebook" => 12, "pencil" => 30 }
    stock.set("eraser", 8)
    stock["ruler"] = 3
    stock.remove("pencil")
    println(stock.length)           // 3
    println(stock.has("pencil"))    // false

    let empty = Map[String]{}
    let typed: Map[bool] = .{ "debug" => true }
    println("%{empty.length} %{typed.length}") // 0 1
}

Look up a value#

Valk
fn main() {
    let stock = Map[int]{ "notebook" => 12 }
    println(stock.get("notebook") !? 0)  // 12
    println(stock.get("stapler") !? -1)  // -1: get throws for a missing key
    println(stock["stapler"])            // 0: [] gives the zero value

    let labels = Map[String]{ "a" => "Apple" }
    println(labels["b"] ?? "none")       // none: null for a missing object
}
  • get(key) throws LookupError.missing when the key is absent.
  • map[key] gives 0, false or null for a missing key. For a class or String value its type is nullable, so use ??.

Loop over a map#

Valk
fn main() {
    let stock = Map[int]{ "pen" => 3, "cup" => 0, "box" => 5 }
    each stock as count, item {
        if count == 0 : stock.remove(item)   // removing while looping is safe
    }
    each stock as count, item, index : println("%index %item: %count")
    let keys = stock.keys()
    keys.sort()
    println(keys.join(", "))   // box, pen
}

Entries are visited in insertion order; removing one can change that order. Call sort_keys() to order a Map by key.

Count and update in place#

Valk
fn main() {
    let counts = Map[uint]{}
    each "the cat and the hat".words() as word {
        counts.add(word, 1)
    }
    println(counts["the"])   // 2

    let scores = Map[int]{}
    scores["ada"] += 5 !? 0  // a missing key starts at 0
    scores.update("sam", fn(old) { return (old ?? 0) + 10 })
    println("%{scores["ada"]} %{scores["sam"]}") // 5 10
}

add works on maps of uint. update gets the old value, or null, and stores what the function returns.

Other key types#

Valk
struct Point {
    x: int
    y: int
}

fn main() {
    let names = HashMap[uint, String]{ 5 => "five", 10 => "ten" }
    println(names[5] ?? "")   // five

    let grid = HashMap[Point, String]{}
    grid.set(Point { x: 1, y: 2 }, "tree")
    println(grid.get(Point { x: 1, y: 2 }) !? "") // tree

    let pairs = HashMap[(int, int), bool]{ (0, 1) => true }
    println(pairs.has((0, 1)))  // true
}

Keys can be integers, strings, structs, tuples, fixed arrays of those, or any type with a hash method. A struct with a float or with its own == needs its own hash.

Map[T] is a HashMap[String, T], and the two convert to each other freely.

Methods#

Method Effect
set(key, value), map[key] = value Add or replace
set_unique(key, value) Add; throws exists when the key is there
get(key) Value; throws when missing
has(key), has_value(value) bool
remove(key) Remove one entry
remove_where(fn), retain(fn) Remove or keep entries the function accepts
keys(), values() Array of keys or values
length, is_empty(), clear() Size and reset
merge(other), merge_in_place(other) Combine maps; other wins on equal keys
copy(), clone() Shallow or deep copy
sort_keys() Order entries by key

For a small map that keeps insertion order also after removals, use FlatMap. To share a map between threads, see Sharing data between threads.