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.
words = input().split()queries = input().split()print(len(set(words)))counts = {}for w in words: counts[w] = counts.get(w, 0) + 1for q in queries: if q in counts: print(q, counts[q]) else: print(q, "none")for w in sorted(counts): print(w, counts[w])const [words, queries] = require("fs").readFileSync(0, "utf8").trim().split("\n").map((l) => l.trim().split(/\s+/));console.log(new Set(words).size);const counts = new Map();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));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));import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String[] words = sc.nextLine().trim().split("\\s+"); String[] queries = sc.nextLine().trim().split("\\s+"); System.out.println(new HashSet<>(Arrays.asList(words)).size()); Map<String, Integer> counts = new TreeMap<>(); for (String w : words) counts.merge(w, 1, Integer::sum); for (String q : queries) { if (counts.containsKey(q)) System.out.println(q + " " + counts.get(q)); else System.out.println(q + " none"); } for (Map.Entry<String, Integer> e : counts.entrySet()) { System.out.println(e.getKey() + " " + e.getValue()); } }}using System;using System.Collections.Generic;using System.Linq; class Program{ static void Main() { string[] words = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); string[] queries = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); Console.WriteLine(new HashSet<string>(words).Count); var counts = new Dictionary<string, int>(); foreach (string w in words) counts[w] = counts.GetValueOrDefault(w) + 1; foreach (string q in queries) { if (counts.TryGetValue(q, out int c)) Console.WriteLine($"{q} {c}"); else Console.WriteLine($"{q} none"); } foreach (string w in counts.Keys.OrderBy(k => k, StringComparer.Ordinal)) Console.WriteLine($"{w} {counts[w]}"); }}#include <iostream>#include <map>#include <set>#include <sstream>#include <string>#include <vector> std::vector<std::string> readWords() { std::string line, w; std::getline(std::cin, line); std::istringstream in(line); std::vector<std::string> out; while (in >> w) out.push_back(w); return out;} int main() { std::vector<std::string> words = readWords(), queries = readWords(); std::cout << std::set<std::string>(words.begin(), words.end()).size() << '\n'; std::map<std::string, int> counts; for (const auto& w : words) counts[w]++; for (const auto& q : queries) { if (counts.contains(q)) std::cout << q << ' ' << counts.at(q) << '\n'; else std::cout << q << " none\n"; } for (const auto& [w, c] : counts) std::cout << w << ' ' << c << '\n';}#include <stdio.h>#include <stdlib.h>#include <string.h> char keys[1000][32];int vals[1000], n = 0; int find(const char *w) { for (int i = 0; i < n; i++) if (strcmp(keys[i], w) == 0) return i; return -1;} int cmp(const void *a, const void *b) { return strcmp(keys[*(const int *)a], keys[*(const int *)b]); } int main(void) { char line[4096], qline[4096]; fgets(line, sizeof line, stdin); fgets(qline, sizeof qline, stdin); for (char *w = strtok(line, " \r\n"); w; w = strtok(NULL, " \r\n")) { int i = find(w); if (i < 0) { strcpy(keys[n], w); vals[n] = 0; i = n++; } vals[i]++; } printf("%d\n", n); for (char *q = strtok(qline, " \r\n"); q; q = strtok(NULL, " \r\n")) { int i = find(q); if (i >= 0) printf("%s %d\n", q, vals[i]); else printf("%s none\n", q); } int order[1000]; for (int i = 0; i < n; i++) order[i] = i; qsort(order, n, sizeof order[0], cmp); for (int i = 0; i < n; i++) printf("%s %d\n", keys[order[i]], vals[order[i]]); return 0;}words = Console.ReadLine().Split();queries = Console.ReadLine().Split();counts = Dict();foreach (w in words){ if (counts.Contains(w)) { counts[w] = counts[w] + 1; } else { counts[w] = 1; }}Console.WriteLine(counts.Count);foreach (q in queries){ if (counts.Contains(q)) { Console.WriteLine(q + " " + counts[q]); } else { Console.WriteLine(q + " none"); }}keys = counts.Keys;keys.Sort();foreach (w in keys){ Console.WriteLine(w + " " + counts[w]);}apple banana apple cherry banana apple banana grape
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
| Python | counts = {} — count with counts.get(w, 0) + 1, check with w in counts.Reading a missing key with [] raises KeyError.Keeps insertion order. Sets: set |
|---|---|
| JavaScript | new Map() — count with (counts.get(w) ?? 0) + 1, check with has.A missing key makes get return undefined.Keeps insertion order. Sets: Set |
| TypeScript | Same as JavaScript. Write the types, as in new Map<string, number>() |
| Java | HashMap (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 |
| C | No 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) |
| Craykon | Dict() — 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).
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.