Map i Set — słowniki oraz zbiory

Policz głosy i usuń duplikaty uczestników. Map łączy klucz z wartością, a Set pilnuje unikalności elementów.

CEL LEKCJI

Po tej lekcji potrafisz

  • Użyjesz set, get, has, delete, clear i size kolekcji Map.
  • Zastosujesz add, has i iterację po Set.
  • Wyjaśnisz równość kluczy obiektowych i kolejność iteracji.
WPROWADZENIE

Głosowanie na grę wieczoru

Dla każdego tytułu chcemy pamiętać liczbę głosów. Szukanie tytułu w kilku tablicach szybko robi się niewygodne. Map daje jasne powiązanie nazwa → licznik. Set przyda się do listy unikalnych uczestników.

POZNAJ SKŁADNIĘ

Małe kroki, konkretne efekty

Map pamięta pary klucz–wartość

Map<string, number> ma tekstowe klucze i liczbowe wartości. set dodaje lub zastępuje wartość pod kluczem. get zwraca wartość albo undefined; size to liczba par.

src/index.ts — osobny przykład
const punkty = new Map<string, number>();
punkty.set("Ala", 10);
punkty.set("Ala", 20);
console.log(punkty.get("Ala"), punkty.size);
console.log(punkty.has("Neo"), punkty.get("Neo") ?? 0);
console.log(punkty.delete("Ala"), punkty.size);
punkty.clear();
wynik w konsoli
20 1
false 0
true 0

delete informuje, czy klucz istniał. clear usuwa wszystkie wpisy. Nie ustawiaj wartości przez punkty[„Ala”] — to inny mechanizm właściwości obiektów.

Set trzyma unikalne wartości

Powtórne add tej samej wartości nie zwiększa zbioru. Set zachowuje kolejność pierwszego dodania pozostających elementów. Ma size, a nie length.

src/index.ts — osobny przykład
const nicki = new Set(["Ala", "Neo", "Ala"]);
nicki.add("Ola");
console.log([...nicki].join(", "), nicki.size);
console.log(nicki.has("Neo"));
nicki.delete("Neo");
console.log([...nicki].join(", "));
nicki.clear();
console.log(nicki.size);
wynik w konsoli
Ala, Neo, Ola 3
true
Ala, Ola
0

Spread zamienia iterowalny zbiór na tablicę. „ala” i „Ala” to różne wartości; ujednolicenie wielkości liter jest osobną decyzją.

PRZYKŁAD Z OMÓWIENIEM

Wyniki głosowania

Każdy wpis w tablicy to głos. Na tym etapie zakładamy, że uprawnienia głosujących sprawdzono wcześniej. Nasz program jedynie zlicza tytuły.

src/index.ts — osobny przykład
const glosy = ["Kosmos", "Wyścigi", "Kosmos", "Puzzle", "Wyścigi", "Kosmos"];
const licznik = new Map<string, number>();
for (const tytul of glosy) {
  licznik.set(tytul, (licznik.get(tytul) ?? 0) + 1);
}
for (const [tytul, liczba] of licznik) {
  console.log(tytul + ": " + liczba);
}
console.log("Gier: " + licznik.size);
wynik w konsoli
Kosmos: 3
Wyścigi: 2
Puzzle: 1
Gier: 3

Jak program dochodzi do wyniku

  1. Brak poprzedniego licznika zastępujemy zerem.
  2. set nadpisuje licznik danego tytułu nową liczbą.
  3. Iteracja Map daje pary [klucz, wartość], które rozpakowujemy destrukturyzacją.
  4. Kolejność wynika z pierwszego dodania kluczy, a nie z liczby głosów.

Zanim przejdziesz dalej

Czy set(„Kosmos”, 99) utworzy drugi wpis Kosmos?

Sprawdź swoje rozumowanie

Nie. Zastąpi wartość istniejącego klucza i nie zwiększy size.

EKSPERYMENT

Zmień kod i zobacz, co się stanie

Obiekty są porównywane przez tożsamość

Dwa osobno utworzone obiekty z tymi samymi polami nie są tym samym kluczem. Zbiór takich obiektów też nie usuwa duplikatów według ich treści.

src/index.ts — osobny przykład
const a = { id: 1 };
const b = { id: 1 };
const zbior = new Set([a, b, a]);
console.log(zbior.size);
const mapa = new Map<object, string>([[a, "Pierwszy"]]);
console.log(mapa.get(b) ?? "Inny obiekt");
console.log([...mapa.values()].join(","));
wynik w konsoli
2
Inny obiekt
Pierwszy

Jeśli unikalność ma zależeć od id, przechowuj id jako klucz. Map i Set uznają NaN za równe NaN, a 0 i -0 za ten sam klucz — to nieco inne reguły niż samo ===.

CZĘSTE BŁĘDY

Gdy wynik zaskakuje

Pomyłka Co się dzieje i jak to poprawić
length zamiast size Map i Set udostępniają liczbę wpisów przez size.
get bez obsługi braku Brak klucza daje undefined.
Set obiektów jako usuwanie duplikatów po id Zbiór porównuje tożsamość obiektów. Wybierz Set identyfikatorów.
ZADANIA

Teraz Twoja kolej

Rozwiązanie jest jedną z możliwości. Zanim je odkryjesz, uruchom własną wersję dla podanych danych i przynajmniej jednego przypadku brzegowego.

ZAD 1Unikalne tagi★☆☆

Usuń powtórzenia z [„ts”, „gry”, „ts”, „kod”] i zachowaj kolejność pierwszego pojawienia.

Mała podpowiedź

Set i spread.

Przykładowe rozwiązanie z wyjaśnieniem
src/index.ts — osobny przykład
console.log([...new Set(["ts", "gry", "ts", "kod"])].join(","));
wynik w konsoli
ts,gry,kod

Nie jest potrzebne sortowanie.

ZAD 2Cennik nagród★★☆

Map ma przechowywać „naklejka” → 5 i „kubek” → 20. Wypisz cenę kubka, usuń naklejkę, sprawdź size.

Mała podpowiedź

set, get, delete.

Przykładowe rozwiązanie z wyjaśnieniem
src/index.ts — osobny przykład
const ceny = new Map<string, number>([["naklejka", 5], ["kubek", 20]]);
console.log(ceny.get("kubek"));
ceny.delete("naklejka");
console.log(ceny.size);
wynik w konsoli
20
1

Klucz daje bezpośredni dostęp do przypisanej wartości.

ZAD 3Wspólni uczestnicy★★☆

Wyznacz wspólne nicki list [„Ala”, „Neo”] i [„Neo”, „Ola”]. Wynik ma nie mieć duplikatów.

Mała podpowiedź

Dwa zbiory i filter z has.

Przykładowe rozwiązanie z wyjaśnieniem
src/index.ts — osobny przykład
const a = new Set(["Ala", "Neo"]);
const b = new Set(["Neo", "Ola"]);
console.log([...a].filter(nick => b.has(nick)).join(","));
wynik w konsoli
Neo

Wybieramy tylko elementy pierwszego zbioru obecne w drugim.

ZAD 4Pierwsze zgłoszenie wygrywa★★★

Dla zgłoszeń o id 1, 2, 1 zaakceptuj tylko pierwsze wystąpienie każdego id. Wypisz „Ala, Neo”, pomijając trzecie zgłoszenie „Max”.

Mała podpowiedź

Set<number> pamięta już widziane identyfikatory.

Przykładowe rozwiązanie z wyjaśnieniem
src/index.ts — osobny przykład
const zgloszenia = [{ id: 1, nick: "Ala" }, { id: 2, nick: "Neo" }, { id: 1, nick: "Max" }];
const widziane = new Set<number>();
const wynik = zgloszenia.filter(z => {
  if (widziane.has(z.id)) { return false; }
  widziane.add(z.id); return true;
});
console.log(wynik.map(z => z.nick).join(", "));
wynik w konsoli
Ala, Neo

To kontrolowany efekt uboczny callbacku; zbiór należy do tej operacji filtrowania.

PODSUMOWANIE

Co zabierasz do następnej lekcji

  • Map łączy klucz z wartością; Set przechowuje unikalne elementy.
  • Kolekcje pamiętają kolejność dodawania, ale nie sortują.
  • Klucze obiektowe są porównywane przez tożsamość.