JavaScript · Syntax · Intermediate

Map

10 tasks

Learn the Map data structure in JavaScript — a key-value collection that accepts any type as a key, preserves insertion order, and provides efficient add, get, and delete operations.

Map: key-value collection with any key type

#
`Map` is a key-value collection, similar to a plain object, but with important differences that make it better in several situations. **Creating a Map and core methods** ```javascript const m = new Map(); m.set('name', 'Alice'); // add or update an entry m.set(42, 'answer'); // number as key — works fine m.set(true, 'yes'); // boolean as key — works fine m.get('name'); // "Alice" m.get(42); // "answer" m.has('name'); // true m.has('phone'); // false m.size; // 3 (property, no parentheses) m.delete('name'); // removes entry, returns true if existed m.clear(); // removes all entries ``` You can also initialize from an array of `[key, value]` pairs: ```javascript const scores = new Map([ ['Alice', 95], ['Bob', 87], ]); ``` **How Map differs from Object** Object only accepts strings and symbols as keys. Map accepts anything — numbers, objects, other Maps, even functions. This matters when you need to use non-string data as a lookup key. Object doesn't have a built-in `size` — you need `Object.keys(obj).length`. Map has `.size` directly. Map preserves insertion order for all key types. Object does too for string keys in modern engines, but not reliably for integer-like strings. Map is directly iterable with `for...of`. Object requires `Object.entries()` or similar. **When to use Map vs Object** Use Map when: - Keys are not strings (numbers, objects, symbols) - You need `.size` without extra code - You're adding and deleting entries frequently (Map is optimized for mutations) - You need a guaranteed iteration order across all key types Keep using Object when: - You have string/symbol keys and don't need the above - You need JSON serialization — `JSON.stringify` ignores Map entries - You're writing config or data you know at write time (object literals are more readable)

Iterating, converting, and using Map as a counter

#
Three patterns cover most real-world Map usage: iterating over entries, converting between Map and Object, and using Map as a frequency counter. **Iterating** ```javascript const m = new Map([['a', 1], ['b', 2], ['c', 3]]); for (const [key, value] of m) { console.log(key, value); // most common form } for (const [key, value] of m.entries()) { console.log(key, value); // identical to the above } for (const key of m.keys()) { console.log(key); } for (const val of m.values()) { console.log(val); } m.forEach((value, key) => { console.log(key, value); // note: value comes first, key second }); ``` `for...of` destructures each entry directly. `forEach` has reversed parameter order compared to array's `forEach` — a frequent source of confusion. **Map as a frequency counter** ```javascript const text = "hello"; const freq = new Map(); for (const ch of text) { freq.set(ch, (freq.get(ch) ?? 0) + 1); } // Map { 'h'=>1, 'e'=>1, 'l'=>2, 'o'=>1 } ``` `freq.get(ch) ?? 0` reads the current count or falls back to 0 if the character isn't yet in the Map. Then `+ 1` increments it. This pattern works for any counter — words, events, categories. **Converting between Map, Object, and Array** ```javascript // Object → Map const obj = { a: 1, b: 2 }; const m = new Map(Object.entries(obj)); // Map → Object const back = Object.fromEntries(m); // Array of pairs → Map const m2 = new Map([['x', 10], ['y', 20]]); // Map → Array of pairs const pairs = [...m.entries()]; // Merging two Maps (later key wins on collision) const m1 = new Map([['a', 1], ['b', 2]]); const m3 = new Map([['b', 99], ['c', 3]]); const merged = new Map([...m1, ...m3]); // b → 99 (m3 overwrites m1) ``` Spread `...` converts a Map to an iterable of pairs — the same format the Map constructor accepts. This is how both the merge and the array-of-pairs conversion work.

Map reference: methods and Map vs Object

#
Quick lookup for Map methods and a comparison with plain Object. **Methods and properties** `new Map()` — empty map `new Map(iterable)` — from `[[key, val], ...]` pairs `map.set(key, val)` — add/update entry; returns the map (chainable) `map.get(key)` — value, or undefined if key is missing `map.has(key)` — true/false `map.delete(key)` — remove one entry; returns true if it existed `map.clear()` — remove all entries `map.size` — number of entries (property, no parentheses) `map.keys()` — iterator over keys `map.values()` — iterator over values `map.entries()` — iterator over [key, value] pairs `map.forEach(fn)` — `fn(value, key, map)` for each entry **Iteration** ```javascript for (const [key, val] of map) { } // most common for (const [key, val] of map.entries()) { } // same for (const key of map.keys()) { } for (const val of map.values()) { } map.forEach((val, key) => { }); // value first, key second ``` **Map vs Object** Key types: Map accepts any value; Object only strings and symbols. Size: `map.size` vs `Object.keys(obj).length`. Iteration: Map is directly iterable; Object needs `Object.entries()`. JSON: `JSON.stringify` skips Map — convert to Object first. Prototype: Map has no inherited properties; Object may inherit from prototype. Performance: Map is optimized for frequent add/delete; Object for static shape. **Common conversions** Object → Map: `new Map(Object.entries(obj))` Map → Object: `Object.fromEntries(map)` Map → Array of pairs: `[...map.entries()]` Merge: `new Map([...m1, ...m2])` — m2 wins on key collision
01

Create a Map and use set, get, has

#

Create a Map with three entries: `"name"` → `"Alice"`, `"age"` → `30`, `"city"` → `"Kyiv"`. Then print: the value for `"name"`, whether `"age"` exists, whether `"phone"` exists.

// your code here
Solution
const m = new Map();
m.set("name", "Alice");
m.set("age", 30);
m.set("city", "Kyiv");

console.log(m.get("name"));
console.log(m.has("age"));
console.log(m.has("phone"));
02

Word frequency counter

#

Count how many times each word appears in `text` using a Map. Print the Map.

let text = "the cat sat on the mat the cat";
// your code here
Solution
let text = "the cat sat on the mat the cat";
const freq = new Map();
for (const word of text.split(" ")) {
    freq.set(word, (freq.get(word) ?? 0) + 1);
}
console.log(freq);
03

Phone book with lookup

#

Create a phone book Map with three contacts: `"Alice"` → `"+380501234567"`, `"Bob"` → `"+380679876543"`, `"Charlie"` → `"+380931112233"`. Look up `"Bob"` — if found print the number, otherwise print `"Not found"`.

// your code here
Solution
const phoneBook = new Map();
phoneBook.set("Alice", "+380501234567");
phoneBook.set("Bob", "+380679876543");
phoneBook.set("Charlie", "+380931112233");

const name = "Bob";
console.log(phoneBook.has(name) ? phoneBook.get(name) : "Not found");
04

Convert Object to Map and back

#

Convert the object `obj` to a Map, print the value for key `"b"`, then convert the Map back to an object and print it.

const obj = { a: 1, b: 2, c: 3 };
// your code here
Solution
const obj = { a: 1, b: 2, c: 3 };
const m = new Map(Object.entries(obj));
console.log(m.get("b"));
const back = Object.fromEntries(m);
console.log(back);
05

Iterate over Map entries

#

Iterate over the `scores` Map and print each entry in the format `"Name: score"` on its own line.

const scores = new Map([["Alice", 95], ["Bob", 87], ["Charlie", 92]]);
// your code here
Solution
const scores = new Map([["Alice", 95], ["Bob", 87], ["Charlie", 92]]);
for (const [name, score] of scores) {
    console.log(`${name}: ${score}`);
}
06

Map as a computation cache

#

Write a function `cachedSquare(n)` that returns `n * n` but stores results in a Map so each number is computed only once. Call it three times: with `5`, `5` again, and `7`. Print each result and the cache size at the end.

const cache = new Map();

function cachedSquare(n) {
    // your code here
}

console.log(cachedSquare(5));
console.log(cachedSquare(5));
console.log(cachedSquare(7));
console.log(cache.size);
Solution
const cache = new Map();

function cachedSquare(n) {
    if (!cache.has(n)) {
        cache.set(n, n * n);
    }
    return cache.get(n);
}

console.log(cachedSquare(5));
console.log(cachedSquare(5));
console.log(cachedSquare(7));
console.log(cache.size);
07

Delete entries below a threshold

#

Remove all entries from `prices` where the price is less than `1.0`. Print the Map after cleanup.

const prices = new Map([["apple", 1.5], ["banana", 0.8], ["cherry", 3.0], ["date", 0.5]]);
const threshold = 1.0;
// your code here
Solution
const prices = new Map([["apple", 1.5], ["banana", 0.8], ["cherry", 3.0], ["date", 0.5]]);
const threshold = 1.0;
for (const [item, price] of prices) {
    if (price < threshold) {
        prices.delete(item);
    }
}
console.log(prices);
08

Merge two Maps

#

Merge `m1` and `m2` into a new Map `merged`. When the same key exists in both, the value from `m2` should win. Print the merged Map.

const m1 = new Map([["a", 1], ["b", 2]]);
const m2 = new Map([["b", 20], ["c", 3]]);
// your code here
Solution
const m1 = new Map([["a", 1], ["b", 2]]);
const m2 = new Map([["b", 20], ["c", 3]]);
const merged = new Map([...m1, ...m2]);
console.log(merged);
09

Find a key by value

#

Find the country in `capitals` whose capital is `"Berlin"`. Print the country name, or `"Not found"` if missing.

const capitals = new Map([["France", "Paris"], ["Germany", "Berlin"], ["Ukraine", "Kyiv"]]);
// your code here
Solution
const capitals = new Map([["France", "Paris"], ["Germany", "Berlin"], ["Ukraine", "Kyiv"]]);
let result = "Not found";
for (const [country, capital] of capitals) {
    if (capital === "Berlin") {
        result = country;
        break;
    }
}
console.log(result);
10

Group array of objects by field

#

Group the `users` array by `role` using a Map. Each key should be a role name, each value an array of names with that role. Print the Map.

const users = [
    { name: "Alice", role: "admin" },
    { name: "Bob", role: "user" },
    { name: "Charlie", role: "admin" },
    { name: "Dave", role: "user" },
];
// your code here
Solution
const users = [
    { name: "Alice", role: "admin" },
    { name: "Bob", role: "user" },
    { name: "Charlie", role: "admin" },
    { name: "Dave", role: "user" },
];
const groups = new Map();
for (const user of users) {
    if (!groups.has(user.role)) {
        groups.set(user.role, []);
    }
    groups.get(user.role).push(user.name);
}
console.log(groups);