{ }codelper

Learn › TypeScript

Going further · 16

Dictionaries (maps)

Find and update values by key: counting words, checking for a key, iterating in key order.

A dictionary (map) finds values by key instead of by position.
The example below counts how often each word appears, looks up the words it is asked about, and prints everything in key order.

import { readFileSync } from "node:fs";const [words, queries]: string[][] = readFileSync(0, "utf8").trim().split("\n").map((l) => l.trim().split(/\s+/));console.log(new Set(words).size);const counts = new Map<string, number>();for (const w of words) counts.set(w, (counts.get(w) ?? 0) + 1);for (const q of queries) {  if (counts.has(q)) console.log(q, counts.get(q));  else console.log(q, "none");}for (const w of [...counts.keys()].sort()) console.log(w, counts.get(w));
stdin
apple banana apple cherry banana apple
banana grape
stdout
3
banana 2
grape none
apple 3
banana 2
cherry 1

Key points

  • You pair keys with values, like "apple" → 3.
    Inserting, finding and updating are far faster than scanning a list from the start.
  • The classic use is counting.
    A word seen for the first time starts at 0 and gets 1 added.
  • Reading a missing key is where languages differ most: an error, an empty value, or a new entry.
    So check first.
  • Do not rely on iteration order.
    Some languages keep insertion order and some promise nothing.
    The example sorts the keys so every language prints the same thing.
  • Keys without values make a set.
    The number of distinct words is just the size of a set.

How each language writes it

Pythoncounts = {} — count with counts.get(w, 0) + 1, check with w in counts.
Reading a missing key with [] raises KeyError.
Keeps insertion order.
Sets: set
JavaScriptnew Map() — count with (counts.get(w) ?? 0) + 1, check with has.
A missing key makes get return undefined.
Keeps insertion order.
Sets: Set
TypeScriptSame as JavaScript.
Write the types, as in new Map<string, number>()
JavaHashMap (no order promised), LinkedHashMap (insertion order), TreeMap (key order).
Count with merge(w, 1, Integer::sum), check with containsKey; a missing key makes get return null.
Sets: HashSet
C#Dictionary<string, int> — count with GetValueOrDefault(w) + 1, check with TryGetValue.
A missing key in the indexer throws KeyNotFoundException.
The order is undefined (use SortedDictionary for key order).
Sets: HashSet
C++std::map (key order), std::unordered_map (no order promised).
Count with counts[w]++, check with C++20 contains.
Reading a missing key with [] creates an entry with value 0.
Sets: std::set
CNo built-in map.
The example keeps an array of keys next to an array of values and searches from the start (fine for small inputs)
CraykonDict() — read and write with d["apple"] = 3.
Check with d.Contains(key); d.Keys comes in insertion order.
Reading a missing key stops with a runtime error, as in Python

Common mistakes

Reading with [] to check created an entryC++

std::map<std::string, int> counts;
if (counts["grape"] == 0) { }
std::cout << counts.size();

→ 1 — just reading it created a "grape" entry with value 0

Check with counts.contains(w) (C++20) or counts.find(w).

Reading a missing key directlyPython · C# · Craykon

counts = {"apple": 3}
print(counts["grape"])

→ Stops with KeyError: 'grape' (C# throws KeyNotFoundException; Craykon says the dictionary has no "grape" key)

Check first, or give a default, as in Python get(w, 0).

Expecting insertion orderJava · C# · C++

Map<String, Integer> m = new HashMap<>();
m.put("pear", 1); m.put("apple", 2); m.put("fig", 3);
System.out.println(m.keySet());

→ [apple, pear, fig] — not the insertion order (pear, apple, fig)

Sort the keys before printing, or use a map that promises an order: TreeMap or LinkedHashMap (C++ std::map, C# SortedDictionary).

How languages differ
Counting in a plain JavaScript object {} collides with words like "constructor" from Object.prototype, and number-like keys such as "10" are listed first in ascending order regardless of insertion.
Use a Map for counting.

Practice