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);