Tablice

Jedna zmienna na jedną ocenę wystarczy do trzeciej lekcji. Przy trzydziestu ocenach potrzebujesz tablicy — struktury, która trzyma wiele wartości pod jedną nazwą i pozwala je przeglądać w pętli.

TypeScript number[] push / splice for…of 50 min
CEL LEKCJI

Czego się dziś nauczysz

  • Zadeklarujesz tablicę o określonym typie elementów i wypełnisz ją danymi
  • Dodasz i usuniesz elementy z początku, końca i środka tablicy
  • Sprawdzisz, czy tablica zawiera daną wartość, i znajdziesz jej pozycję
  • Przejdziesz przez wszystkie elementy pętlą for…of
  • Zamienisz tekst na tablicę i tablicę na tekst
TEORIA

Tworzenie tablicy

Tablica to ponumerowana lista elementów. W number[] każdy element ma być liczbą. Typ elementu może również być unią, więc TypeScript pozwala też opisać tablice mieszane.

src/index.ts
const oceny: number[] = [5, 4, 3, 5, 4];
const uczniowie: string[] = ["Ala", "Bartek", "Cezary"];
const obecnosci: boolean[] = [true, true, false, true];

// typ można pominąć — kompilator wywnioskuje go z zawartości
const punkty = [12, 8, 20];        // number[]
const przedmioty = ["INF.04", "matematyka"];   // string[]

// pusta tablica MUSI mieć podany typ
const wyniki: number[] = [];       // dobrze
const cos = [];                    // any[] — kompilator nie ma czego się chwycić

Drugi sposób zapisu

Spotkasz też zapis Array<number> — znaczy dokładnie to samo co number[]. W praktyce częściej używa się krótszej formy; ta druga przyda się przy generykach w lekcji 22.

Tablica zadeklarowana jako const nie może zostać podmieniona na inną tablicę, ale jej zawartość wolno zmieniać:

Celowy błąd: const nie pozwala podmienić tablicy
const lista = [1, 2, 3];

lista.push(4);       // OK — modyfikujemy zawartość
lista[0] = 99;       // OK
console.log(lista);  // [99, 2, 3, 4]

lista = [5, 6];      // Błąd TS2588 — to już podmiana całej tablicy
TEORIA

Dostęp do elementów

numerowanie elementów
const oceny = [ 5 ,  4 ,  3 ,  5 ,  4 ];
                │    │    │    │    │
indeks:         0    1    2    3    4
                                     └── oceny.length - 1
oceny.length = 5
src/index.ts
const oceny = [5, 4, 3, 5, 4];

console.log(oceny[0]);                  // 5 — pierwszy element
console.log(oceny[2]);                  // 3
console.log(oceny.length);              // 5 — liczba elementów
console.log(oceny[oceny.length - 1]);   // 4 — ostatni element
console.log(oceny.at(-1));              // 4 — krócej, to samo

oceny[1] = 6;                           // podmiana elementu
console.log(oceny);                     // [5, 6, 3, 5, 4]

console.log(oceny[10]);                 // undefined — poza zakresem!

Poza zakresem nie ma wyjątku

W C# odwołanie poza tablicę kończy się wyjątkiem. Tutaj dostaniesz po prostu undefined, a program pobiegnie dalej z pustą wartością, która zepsuje obliczenia gdzieś zupełnie indziej. Zawsze pilnuj, żeby indeks mieścił się w przedziale od 0 do length - 1.

PRAKTYKA

Dodawanie i usuwanie elementów

src/index.ts
const kolejka: string[] = ["Ala", "Bartek"];

kolejka.push("Cezary");        // na koniec       → ["Ala","Bartek","Cezary"]
kolejka.unshift("Zofia");      // na początek     → ["Zofia","Ala","Bartek","Cezary"]

const ostatni = kolejka.pop();     // usuwa z końca i zwraca      → "Cezary"
const pierwszy = kolejka.shift();  // usuwa z początku i zwraca   → "Zofia"

console.log(kolejka);          // ["Ala", "Bartek"]
console.log(`Obsłużono: ${pierwszy}, odesłano: ${ostatni}`);

Usuwanie ze środka — splice

src/index.ts
const lista = ["a", "b", "c", "d", "e"];

lista.splice(1, 2);              // od pozycji 1 usuń 2 elementy
console.log(lista);              // ["a", "d", "e"]

lista.splice(1, 0, "X", "Y");    // od pozycji 1 usuń 0, wstaw X i Y
console.log(lista);              // ["a", "X", "Y", "d", "e"]
MetodaDziałanieZwraca
push(x)dodaje na koniecnową długość tablicy
pop()usuwa ostatniusunięty element
unshift(x)dodaje na począteknową długość tablicy
shift()usuwa pierwszyusunięty element
splice(od, ile, …)usuwa i/lub wstawia w środkutablicę usuniętych

Skojarzenie, które ułatwia zapamiętanie

push i pop pracują na końcu tablicy — to zachowanie stosu (ostatni wchodzi, pierwszy wychodzi). push i shift razem dają kolejkę (pierwszy wchodzi, pierwszy wychodzi) — dokładnie jak kolejka do sklepiku.

PRAKTYKA

Szukanie i sprawdzanie

src/index.ts
const przedmioty = ["INF.03", "INF.04", "matematyka", "angielski"];

console.log(przedmioty.includes("INF.04"));   // true
console.log(przedmioty.indexOf("matematyka")); // 2
console.log(przedmioty.indexOf("chemia"));     // -1 — nie ma

// wycinek — nie zmienia oryginału
console.log(przedmioty.slice(0, 2));           // ["INF.03", "INF.04"]
console.log(przedmioty.slice(-2));             // ["matematyka", "angielski"]

// łączenie i odwracanie
const wiecej = przedmioty.concat(["fizyka"]);
console.log(wiecej.length);                    // 5
console.log([...przedmioty].reverse());        // kopia w odwrotnej kolejności

Uwaga: reverse i sort zmieniają oryginał

W przeciwieństwie do tekstu, tablice modyfikowalne — reverse() i sort() przestawiają elementy w istniejącej tablicy i zwracają ją samą. Zapis [...tablica] tworzy kopię, na której możesz działać bez psucia oryginału.

Sortowanie

src/index.ts
const imiona = ["Zofia", "Ala", "Bartek"];
imiona.sort();
console.log(imiona);            // ["Ala", "Bartek", "Zofia"] — alfabetycznie

const liczby = [10, 9, 100, 2];
liczby.sort();
console.log(liczby);            // [10, 100, 2, 9]  ← to nie pomyłka!

liczby.sort((a, b) => a - b);
console.log(liczby);            // [2, 9, 10, 100] — poprawnie

Domyślnie sort() porównuje elementy jak tekst — dlatego "100" trafia przed "2". Przy liczbach trzeba podać sposób porównywania: (a, b) => a - b dla rosnąco, (a, b) => b - a dla malejąco. Zapis ze strzałką poznasz dokładnie w lekcji 13 — na razie potraktuj go jak gotowy wzorzec.

TEORIA

Przeglądanie tablicy

Najczytelniejszy sposób to pętla for…of, która sama pobiera kolejne elementy:

src/index.ts
const oceny = [5, 4, 3, 5, 4];

// wariant 1 — for…of: gdy potrzebujesz tylko wartości
let suma = 0;
for (const ocena of oceny) {
  suma += ocena;
}
console.log(`Suma: ${suma}, średnia: ${(suma / oceny.length).toFixed(2)}`);

// wariant 2 — klasyczna pętla for: gdy potrzebujesz też numeru pozycji
for (let i = 0; i < oceny.length; i++) {
  console.log(`${i + 1}. ocena: ${oceny[i]}`);
}

// wariant 3 — forEach: numer dostajesz jako drugi argument
oceny.forEach((ocena, indeks) => {
  console.log(`[${indeks}] = ${ocena}`);
});
wynik pierwszych dwóch pętli
Suma: 21, średnia: 4.20
1. ocena: 5
2. ocena: 4
3. ocena: 3
4. ocena: 5
5. ocena: 4
[0] = 5
[1] = 4
[2] = 3
[3] = 5
[4] = 4

Nie myl for…of z for…in

for (const x of tablica) daje wartości. for (const x in tablica) daje indeksy jako tekst — dla tablic praktycznie nigdy nie jest tym, czego chcesz. Zapamiętaj: of jak obiekty w środku.

PRAKTYKA

Tablica a tekst

Dwie metody, które będziesz stosować w każdym projekcie przetwarzającym dane:

src/index.ts
// tekst → tablica
const csv = "Ala;Bartek;Cezary;Dorota";
const imiona = csv.split(";");
console.log(imiona);              // ["Ala","Bartek","Cezary","Dorota"]
console.log(imiona.length);       // 4

const zdanie = "programowanie jest fajne";
console.log(zdanie.split(" "));   // podział na słowa
console.log("abc".split(""));     // ["a","b","c"] — na pojedyncze znaki

// tablica → tekst
const przedmioty = ["INF.03", "INF.04"];
console.log(przedmioty.join(", "));       // "INF.03, INF.04"
console.log(przedmioty.join(" | "));      // "INF.03 | INF.04"
console.log(przedmioty.join(""));         // "INF.03INF.04"

split i join wystarczają do naszego prostego formatu rozdzielanego separatorem. Pełny CSV dopuszcza cytowane pola i separatory wewnątrz nich, dlatego do ogólnego CSV potrzebny jest parser obsługujący jego reguły.

PRZYKŁAD Z OMÓWIENIEM

Dziennik ocen

Program wczytuje oceny zapisane w jednym wierszu (tak jak przyszłyby z pliku), liczy statystyki i rysuje wykres słupkowy w konsoli.

src/index.ts
// ── dane, tak jak przyszłyby z pliku CSV ──
const wiersz = "5;4;3;5;2;4;5;3;4;6";
const uczen = "Marta Kowalska";

// ── 1. Zamiana tekstu na tablicę liczb ──
const teksty: string[] = wiersz.split(";");
const oceny: number[] = [];
for (const t of teksty) {
  oceny.push(Number(t));
}

// ── 2. Podstawowe statystyki ──
let suma = 0;
let najwyzsza = oceny[0];
let najnizsza = oceny[0];

for (const ocena of oceny) {
  suma += ocena;
  if (ocena > najwyzsza) najwyzsza = ocena;
  if (ocena < najnizsza) najnizsza = ocena;
}

const srednia = suma / oceny.length;
const liczbaJedynek = oceny.filter(o => o === 1).length;
const zagrozenie = srednia < 2.0;

// ── 3. Raport ──
console.log("═".repeat(42));
console.log(`DZIENNIK — ${uczen}`);
console.log("═".repeat(42));
console.log(`Oceny:      ${oceny.join(", ")}`);
console.log(`Liczba:     ${oceny.length}`);
console.log(`Średnia:    ${srednia.toFixed(2)}`);
console.log(`Najwyższa:  ${najwyzsza}   Najniższa: ${najnizsza}`);
console.log(`Jedynki:    ${liczbaJedynek}`);
console.log(`Zagrożenie: ${zagrozenie ? "TAK" : "nie"}`);
console.log("─".repeat(42));

// ── 4. Wykres słupkowy: ile razy wystąpiła każda ocena ──
const licznik = [0, 0, 0, 0, 0, 0, 0];   // indeksy 1–6, zero nieużywane
for (const ocena of oceny) {
  licznik[ocena] = licznik[ocena] + 1;
}

for (let stopien = 1; stopien <= 6; stopien++) {
  const ile = licznik[stopien];
  console.log(`${stopien} │ ${"█".repeat(ile)} ${ile > 0 ? ile : ""}`);
}
wynik w konsoli
══════════════════════════════════════════
DZIENNIK — Marta Kowalska
══════════════════════════════════════════
Oceny:      5, 4, 3, 5, 2, 4, 5, 3, 4, 6
Liczba:     10
Średnia:    4.10
Najwyższa:  6   Najniższa: 2
Jedynki:    0
Zagrożenie: nie
──────────────────────────────────────────
1 │ 
2 │ █ 1
3 │ ██ 2
4 │ ███ 3
5 │ ███ 3
6 │ █ 1

Trzy techniki warte zapamiętania

TechnikaNa czym polega
Budowanie tablicy w pętli Zaczynamy od pustej const oceny: number[] = [] i dokładamy elementy przez push. To najczęstszy wzorzec przetwarzania danych wejściowych.
Szukanie minimum i maksimum Zmienne startują od pierwszego elementu, nie od zera. Gdyby najnizsza zaczynała od 0, żadna ocena nigdy nie byłaby od niej mniejsza.
Tablica jako licznik licznik[ocena]++ zlicza wystąpienia bez żadnego if: numer indeksu jest zliczaną wartością. Ta sztuczka pojawia się w wielu zadaniach z sortowania i statystyki.

Co to za filter

oceny.filter(o => o === 1).length zlicza jedynki jedną linijką — tworzy tablicę tylko z pasujących elementów i mierzy jej długość. Cała rodzina takich metod (map, filter, reduce) czeka na nas w lekcji 23. Na razie wystarczy, że rozpoznajesz zapis.

CZĘSTE BŁĘDY

Na co uważać

KodProblem
for (let i = 0; i <= t.length; i++) Klasyk. Ostatni obieg sięga poza tablicę i daje undefined. Ma być i < t.length.
const oceny = []; Przy pustej tablicy podaj typ, np. const oceny: number[] = [];. Bez niego wynik wnioskowania zależy od kontekstu i może być mniej czytelny.
[10, 9, 100].sort() Sortowanie jak tekst. Przy liczbach podaj (a, b) => a - b.
const kopia = oryginal; To nie jest kopia — obie nazwy wskazują tę samą tablicę, więc zmiana w jednej widoczna jest w drugiej. Kopię robi [...oryginal].
tablica.length() length to właściwość — bez nawiasów.
oceny.push("5") Do number[] nie wolno wstawić tekstu. Błąd TS2345 — i bardzo dobrze, bo to on chroni przed pomyłką z lekcji 1.

Pętla na zapas

Do przejścia przez tablicę potrzebna jest pętla, więc poznajesz ją tutaj w najprostszej postaci — for…of bierze kolejne elementy i nie wymaga liczenia indeksów. Wszystkie rodzaje pętli, sterowanie ich przebiegiem przez break i continue oraz pętle zagnieżdżone omawia lekcja 10. Zadania z tej lekcji wymagają wyłącznie tego, co widzisz wyżej.

ZADANIA

Zadania

ZAD 1Przewidź wynik★☆☆
zagadka.ts
const t = [3, 1, 4, 1, 5];
console.log(t.length);
console.log(t[1]);
console.log(t.indexOf(1));
console.log(t.includes(9));
t.push(9);
console.log(t.pop());
console.log(t.slice(1, 3));
console.log(t.join("-"));
pokaż rozwiązanie
5
1
1          indexOf zwraca pozycję PIERWSZEGO wystąpienia
false
9          pop zwraca to, co właśnie dodaliśmy
[1, 4]     slice(1,3) bierze indeksy 1 i 2
3-1-4-1-5
ZAD 2Lista obecności★☆☆

Utwórz tablicę z imionami sześciu uczniów. Wypisz ją w postaci ponumerowanej listy (1. Ala, 2. Bartek…), a pod nią podaj liczbę uczniów oraz imię pierwsze i ostatnie alfabetycznie.

pokaż rozwiązanie
const uczniowie = ["Zofia", "Ala", "Bartek", "Dorota", "Cezary", "Ewa"];

for (let i = 0; i < uczniowie.length; i++) {
  console.log(`${i + 1}. ${uczniowie[i]}`);
}

const posortowani = [...uczniowie].sort();
console.log(`Razem: ${uczniowie.length}`);
console.log(`Pierwszy alfabetycznie:  ${posortowani[0]}`);
console.log(`Ostatni alfabetycznie:   ${posortowani.at(-1)}`);

Zwróć uwagę na [...uczniowie] — sortujemy kopię, żeby oryginalna kolejność listy obecności została nienaruszona.

ZAD 3Statystyki temperatur★★☆

Mając tablicę temperatur z siedmiu dni (mogą być ujemne), policz i wypisz: średnią, wartość najwyższą i najniższą, liczbę dni z mrozem oraz numery dni cieplejszych niż średnia.

pokaż rozwiązanie
const temperatury = [-3, 0, 2, -5, 1, 4, -1];
const dni = ["pon", "wt", "śr", "czw", "pt", "sob", "niedz"];

let suma = 0;
let maks = temperatury[0];
let min = temperatury[0];
let mrozne = 0;

for (const t of temperatury) {
  suma += t;
  if (t > maks) maks = t;
  if (t < min) min = t;
  if (t < 0) mrozne++;
}

const srednia = suma / temperatury.length;
console.log(`Średnia:   ${srednia.toFixed(1)}°C`);
console.log(`Maksimum:  ${maks}°C, minimum: ${min}°C`);
console.log(`Dni z mrozem: ${mrozne}`);

for (let i = 0; i < temperatury.length; i++) {
  if (temperatury[i] > srednia) {
    console.log(`Powyżej średniej: ${dni[i]} (${temperatury[i]}°C)`);
  }
}

Dwie tablice o tej samej długości, przeglądane wspólnym indeksem — to bardzo częsty wzorzec. Wygodniejszy sposób (jedna tablica obiektów) poznasz w lekcji 14.

ZAD 4Kolejka do sklepiku★★☆

Zasymuluj kolejkę: zacznij od trzech osób, dopisz dwie kolejne na koniec, obsłuż dwie pierwsze (usuń je z początku i wypisz komunikat), a jednej osobie pozwól wejść na sam początek jako nauczycielowi. Po każdej operacji wypisuj aktualny stan kolejki i jej długość.

ZAD 5Analiza wyników egzaminu★★★

Wyniki egzaminu przyszły jako jeden tekst: "Ala:78;Bartek:45;Cezary:92;Dorota:31;Ewa:60". Rozbij go na dane, a następnie wypisz tabelkę: imię (wyrównane do 10 znaków), wynik, pasek z gwiazdek (jedna gwiazdka na 10 punktów) oraz status zdania (próg 50%). Na końcu podaj średnią i zdawalność w procentach.

pokaż rozwiązanie
const dane = "Ala:78;Bartek:45;Cezary:92;Dorota:31;Ewa:60";
const PROG = 50;

const rekordy = dane.split(";");
const imiona: string[] = [];
const wyniki: number[] = [];

for (const rekord of rekordy) {
  const czesci = rekord.split(":");
  imiona.push(czesci[0]);
  wyniki.push(Number(czesci[1]));
}

let suma = 0;
let zdalo = 0;

console.log("IMIĘ".padEnd(10) + "WYNIK  WYKRES");
console.log("─".repeat(34));

for (let i = 0; i < imiona.length; i++) {
  const w = wyniki[i];
  const pasek = "*".repeat(Math.floor(w / 10));
  const status = w >= PROG ? "zdał" : "nie zdał";
  console.log(imiona[i].padEnd(10) + String(w).padStart(3) + "%  " + pasek.padEnd(10) + status);
  suma += w;
  if (w >= PROG) zdalo++;
}

console.log("─".repeat(34));
console.log(`Średnia:    ${(suma / wyniki.length).toFixed(1)}%`);
console.log(`Zdawalność: ${((zdalo / wyniki.length) * 100).toFixed(0)}%`);

Rozbijamy nasz umowny tekst najpierw na rekordy, potem na pola. To nie jest uniwersalny parser CSV — działa, ponieważ w tym zadaniu imiona i wyniki nie zawierają separatorów.

PODSUMOWANIE

Co trzeba zapamiętać

  • Typ tablicy to typ elementów plus []: number[], string[].
  • Pustej tablicy nadawaj czytelny typ, np. number[]. Bez kontekstu jej wnioskowanie może zależeć od miejsca i opcji kompilatora (np. any[] lub never[]).
  • Indeksy idą od 0 do length - 1; poza zakresem dostaniesz undefined.
  • push/pop obsługują koniec, unshift/shift początek, splice środek.
  • sort() i reverse() zmieniają oryginał — kopiuj przez [...tablica].
  • split zamienia tekst na tablicę, join tablicę na tekst.
  • for…of daje wartości i to jego używaj domyślnie.