JavaScript · Синтаксис · Проміжний

Map

10 завдань

Вивчи структуру даних Map у JavaScript — колекцію ключ-значення, яка приймає будь-який тип як ключ, зберігає порядок вставки та забезпечує ефективні операції додавання, отримання і видалення.

Map: колекція ключ-значення з довільним типом ключа

#
`Map` — це колекція ключ-значення, схожа на звичайний об'єкт, але з важливими відмінностями, які роблять її кращим вибором у певних ситуаціях. **Створення Map та основні методи** ```javascript const m = new Map(); m.set('name', 'Alice'); // додати або оновити запис m.set(42, 'answer'); // число як ключ — працює m.set(true, 'yes'); // булеве значення як ключ — працює m.get('name'); // "Alice" m.get(42); // "answer" m.has('name'); // true m.has('phone'); // false m.size; // 3 (властивість, без дужок) m.delete('name'); // видаляє запис, повертає true якщо існував m.clear(); // видаляє всі записи ``` Можна також ініціалізувати з масиву пар `[key, value]`: ```javascript const scores = new Map([ ['Alice', 95], ['Bob', 87], ]); ``` **Чим Map відрізняється від Object** Object приймає лише рядки та символи як ключі. Map приймає що завгодно — числа, об'єкти, інші Map, навіть функції. Це важливо коли потрібно використовувати не-рядкові дані як ключ пошуку. В Object немає вбудованого `size` — потрібно `Object.keys(obj).length`. У Map є `.size` напряму. Map зберігає порядок вставки для всіх типів ключів. Object також для рядкових ключів у сучасних рушіях, але не гарантовано для ключів що виглядають як цілі числа. Map безпосередньо ітерується через `for...of`. Object потребує `Object.entries()` або аналогів. **Коли використовувати Map замість Object** Обирай Map коли: - Ключі не є рядками (числа, об'єкти, символи) - Потрібен `.size` без зайвого коду - Часто додаєш і видаляєш записи (Map оптимізований для мутацій) - Потрібен гарантований порядок ітерації для всіх типів ключів Залишай Object коли: - Маєш рядкові/символьні ключі і не потребуєш вищезазначеного - Потрібна JSON-серіалізація — `JSON.stringify` ігнорує записи Map - Пишеш конфіг або дані відомі в момент написання коду (об'єктні літерали читабельніші)

Ітерація, конвертація та Map як лічильник

#
Три паттерни покривають більшість реального використання Map: ітерація по записах, конвертація між Map і Object, та Map як лічильник частоти. **Ітерація** ```javascript const m = new Map([['a', 1], ['b', 2], ['c', 3]]); for (const [key, value] of m) { console.log(key, value); // найпоширеніша форма } for (const [key, value] of m.entries()) { console.log(key, value); // ідентично до вищого } 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); // увага: value йде першим, key другим }); ``` `for...of` деструктурує кожен запис напряму. У `forEach` зворотній порядок параметрів порівняно з `forEach` масиву — часте джерело помилок. **Map як лічильник частоти** ```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` читає поточний лічильник або повертає 0 якщо символу ще немає в Map. Потім `+ 1` збільшує його. Цей паттерн працює для будь-яких лічильників — слів, подій, категорій. **Конвертація між Map, Object і Array** ```javascript // Object → Map const obj = { a: 1, b: 2 }; const m = new Map(Object.entries(obj)); // Map → Object const back = Object.fromEntries(m); // Масив пар → Map const m2 = new Map([['x', 10], ['y', 20]]); // Map → Масив пар const pairs = [...m.entries()]; // Злиття двох Map (при збігу ключа перемагає останній) 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 перезаписує m1) ``` Spread `...` перетворює Map на ітерабельний масив пар — той самий формат що приймає конструктор Map. Саме так працює і злиття, і конвертація в масив пар.

Довідник Map: методи та порівняння з Object

#
Швидкий довідник методів Map та порівняння зі звичайним Object. **Методи та властивості** `new Map()` — порожня Map `new Map(iterable)` — з масиву пар `[[key, val], ...]` `map.set(key, val)` — додати/оновити запис; повертає map (ланцюжок) `map.get(key)` — значення, або undefined якщо ключа немає `map.has(key)` — true/false `map.delete(key)` — видалити запис; повертає true якщо існував `map.clear()` — видалити всі записи `map.size` — кількість записів (властивість, без дужок) `map.keys()` — ітератор ключів `map.values()` — ітератор значень `map.entries()` — ітератор пар [key, value] `map.forEach(fn)` — `fn(value, key, map)` для кожного запису **Ітерація** ```javascript for (const [key, val] of map) { } // найпоширеніше for (const [key, val] of map.entries()) { } // те саме for (const key of map.keys()) { } for (const val of map.values()) { } map.forEach((val, key) => { }); // value першим, key другим ``` **Map vs Object** Типи ключів: Map приймає будь-яке значення; Object лише рядки і символи. Розмір: `map.size` проти `Object.keys(obj).length`. Ітерація: Map напряму ітерується; Object потребує `Object.entries()`. JSON: `JSON.stringify` пропускає Map — конвертуй в Object спочатку. Прототип: Map не має успадкованих властивостей; Object може успадковувати з прототипу. Продуктивність: Map оптимізований для частих додавань/видалень; Object для статичної форми. **Поширені конвертації** Object → Map: `new Map(Object.entries(obj))` Map → Object: `Object.fromEntries(map)` Map → Масив пар: `[...map.entries()]` Злиття: `new Map([...m1, ...m2])` — при збігу ключа m2 перемагає
01

Створити Map та використати set, get, has

#

Створи Map з трьома записами: `"name"` → `"Alice"`, `"age"` → `30`, `"city"` → `"Kyiv"`. Потім виведи: значення для `"name"`, чи існує `"age"`, чи існує `"phone"`.

// твій код тут
Рішення
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

Лічильник частоти слів

#

Порахуй скільки разів кожне слово зустрічається в `text` за допомогою Map. Виведи Map.

let text = "the cat sat on the mat the cat";
// твій код тут
Рішення
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

Телефонна книга з пошуком

#

Створи Map телефонної книги з трьома контактами: `"Alice"` → `"+380501234567"`, `"Bob"` → `"+380679876543"`, `"Charlie"` → `"+380931112233"`. Знайди `"Bob"` — якщо є — виведи номер, інакше — `"Not found"`.

// твій код тут
Рішення
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

Конвертація Object у Map і назад

#

Конвертуй об'єкт `obj` у Map, виведи значення для ключа `"b"`, потім конвертуй Map назад в об'єкт і виведи його.

const obj = { a: 1, b: 2, c: 3 };
// твій код тут
Рішення
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

Ітерація по записах Map

#

Перебери Map `scores` та виведи кожен запис у форматі `"Name: score"` на окремому рядку.

const scores = new Map([["Alice", 95], ["Bob", 87], ["Charlie", 92]]);
// твій код тут
Рішення
const scores = new Map([["Alice", 95], ["Bob", 87], ["Charlie", 92]]);
for (const [name, score] of scores) {
    console.log(`${name}: ${score}`);
}
06

Map як кеш обчислень

#

Напиши функцію `cachedSquare(n)`, яка повертає `n * n` але зберігає результати в Map щоб кожне число обчислювалося лише раз. Викличи тричі: з `5`, знову `5` і `7`. Виведи кожен результат та розмір кешу наприкінці.

const cache = new Map();

function cachedSquare(n) {
    // твій код тут
}

console.log(cachedSquare(5));
console.log(cachedSquare(5));
console.log(cachedSquare(7));
console.log(cache.size);
Рішення
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

Видалити записи нижче порогу

#

Видали з `prices` всі записи де ціна менша за `1.0`. Виведи Map після очищення.

const prices = new Map([["apple", 1.5], ["banana", 0.8], ["cherry", 3.0], ["date", 0.5]]);
const threshold = 1.0;
// твій код тут
Рішення
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

Злиття двох Map

#

Об'єднай `m1` і `m2` у нову Map `merged`. Якщо один і той самий ключ є в обох — значення з `m2` перемагає. Виведи об'єднану Map.

const m1 = new Map([["a", 1], ["b", 2]]);
const m2 = new Map([["b", 20], ["c", 3]]);
// твій код тут
Рішення
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

Знайти ключ за значенням

#

Знайди країну в `capitals` чия столиця — `"Berlin"`. Виведи назву країни, або `"Not found"` якщо не знайдено.

const capitals = new Map([["France", "Paris"], ["Germany", "Berlin"], ["Ukraine", "Kyiv"]]);
// твій код тут
Рішення
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

Групування масиву об'єктів за полем

#

Згрупуй масив `users` за полем `role` за допомогою Map. Кожен ключ — назва ролі, кожне значення — масив імен з цією роллю. Виведи Map.

const users = [
    { name: "Alice", role: "admin" },
    { name: "Bob", role: "user" },
    { name: "Charlie", role: "admin" },
    { name: "Dave", role: "user" },
];
// твій код тут
Рішення
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);