Struktury danych – listy, Krotki, słowniki w Pythonie.

def struktury_danych():
    # ============================================
    # STRUKTURY DANYCH – CO TO JEST?
    # ============================================
    # Do tej pory używaliśmy pojedynczych zmiennych:
    # liczba = 5
    # imie = "Jan"
    #
    # Ale co zrobić, gdy chcemy przechować wiele danych?
    #
    # W Pythonie bardzo często używamy:
    #
    # LISTA   -> []
    # KROTKA  -> ()
    # SŁOWNIK -> {}
    #
    # Każda z tych struktur działa inaczej:
    #
    # LISTA:
    # - przechowuje wiele elementów
    # - można ją zmieniać
    # - elementy mają indeksy: 0, 1, 2...
    #
    # KROTKA:
    # - też przechowuje wiele elementów
    # - ale po utworzeniu nie można jej zmieniać
    # - również używa indeksów
    #
    # SŁOWNIK:
    # - przechowuje dane w parach: klucz : wartość
    # - zamiast indeksów używa nazw, czyli kluczy
    # ============================================

    print("=== LISTA ===")

    # ============================================
    # LISTA – UPORZĄDKOWANY ZBIÓR DANYCH,
    # KTÓRY MOŻNA ZMIENIAĆ
    # ============================================
    # Lista nadaje się np. do przechowywania:
    # - ocen
    # - imion
    # - liczb
    # - wyników
    #
    # Elementy listy zapisujemy w nawiasach []
    # ============================================

    liczby = [10, 20, 30]
    print("Lista:", liczby)

    # --------------------------------------------
    # ODCZYT ELEMENTU
    # --------------------------------------------
    # Indeksy w Pythonie zaczynają się od 0
    # liczby[0] -> pierwszy element
    # liczby[1] -> drugi element
    # liczby[2] -> trzeci element
    print("Pierwszy element:", liczby[0])

    # Możemy też pobrać ostatni element
    print("Ostatni element:", liczby[-1])

    # --------------------------------------------
    # ZMIANA ELEMENTU
    # --------------------------------------------
    # Możemy podmienić wybrany element
    liczby[1] = 99
    print("Po zmianie drugiego elementu:", liczby)

    # --------------------------------------------
    # DODAWANIE ELEMENTU
    # --------------------------------------------
    # append() dodaje element na koniec listy
    liczby.append(40)
    print("Po dodaniu elementu:", liczby)

    # --------------------------------------------
    # USUWANIE ELEMENTU
    # --------------------------------------------
    # pop() bez argumentu usuwa ostatni element
    liczby.pop()
    print("Po usunięciu ostatniego elementu:", liczby)

    # remove() usuwa konkretną wartość
    # UWAGA:
    # usuwa pierwsze znalezione wystąpienie tej wartości
    liczby2 = [5, 10, 15, 10]
    liczby2.remove(10)
    print("Lista po remove(10):", liczby2)

    # --------------------------------------------
    # WYSZUKIWANIE ELEMENTU
    # --------------------------------------------
    # Operator in sprawdza, czy element istnieje
    if 20 in liczby:
        print("20 jest w liście")
    else:
        print("20 nie ma w liście")

    # --------------------------------------------
    # SPRAWDZANIE INDEKSU ELEMENTU
    # --------------------------------------------
    # index() zwraca indeks pierwszego znalezionego elementu
    # UWAGA:
    # jeśli elementu nie ma w liście, program zgłosi błąd
    print("Indeks liczby 30:", liczby.index(30))

    # --------------------------------------------
    # DŁUGOŚĆ LISTY
    # --------------------------------------------
    # len() zwraca liczbę elementów
    print("Długość listy:", len(liczby))

    # --------------------------------------------
    # PĘTLA PO LIŚCIE
    # --------------------------------------------
    print("Elementy listy:")
    for x in liczby:
        print(x)

    # --------------------------------------------
    # SUMA ELEMENTÓW LISTY
    # --------------------------------------------
    suma = 0
    for x in liczby:
        suma += x
    print("Suma elementów listy:", suma)

    # --------------------------------------------
    # ŁĄCZENIE LIST
    # --------------------------------------------
    druga = [100, 200]
    razem = liczby + druga
    print("Połączone listy:", razem)

    # --------------------------------------------
    # SORTOWANIE LISTY
    # --------------------------------------------
    liczby3 = [8, 3, 12, 1]
    liczby3.sort()
    print("Posortowana lista rosnąco:", liczby3)

    # --------------------------------------------
    # ODWRACANIE KOLEJNOŚCI ELEMENTÓW
    # --------------------------------------------
    # reverse() nie sortuje
    # tylko odwraca obecną kolejność elementów
    liczby3.reverse()
    print("Lista po reverse():", liczby3)

    # --------------------------------------------
    # KOPIOWANIE LISTY
    # --------------------------------------------
    # copy() tworzy kopię listy
    kopia = liczby.copy()
    print("Kopia listy:", kopia)


    print("\n=== KROTKA ===")

    # ============================================
    # KROTKA – UPORZĄDKOWANY ZBIÓR DANYCH,
    # KTÓREGO NIE MOŻNA ZMIENIAĆ
    # ============================================
    # Krotka nie jest listą.
    # To osobny typ danych.
    #
    # Wygląda podobnie do listy, ale:
    # - nie można zmieniać jej elementów
    # - nie można dodawać nowych elementów append()
    # - nie można usuwać elementów pop()
    #
    # Krotki używa się wtedy, gdy dane mają pozostać stałe
    # ============================================

    dane = (1, 2, 3)
    print("Krotka:", dane)

    # --------------------------------------------
    # ODCZYT ELEMENTU
    # --------------------------------------------
    print("Pierwszy element krotki:", dane[0])

    # Możemy też odczytać ostatni element
    print("Ostatni element krotki:", dane[-1])

    # --------------------------------------------
    # DŁUGOŚĆ KROTKI
    # --------------------------------------------
    print("Długość krotki:", len(dane))

    # --------------------------------------------
    # WYSZUKIWANIE ELEMENTU
    # --------------------------------------------
    if 2 in dane:
        print("2 jest w krotce")
    else:
        print("2 nie ma w krotce")

    # --------------------------------------------
    # INDEKS ELEMENTU
    # --------------------------------------------
    print("Indeks liczby 3 w krotce:", dane.index(3))

    # --------------------------------------------
    # LICZBA WYSTĄPIEŃ ELEMENTU
    # --------------------------------------------
    dane2 = (1, 2, 2, 3, 2)
    print("Ile razy występuje 2:", dane2.count(2))

    # --------------------------------------------
    # PĘTLA PO KROTCE
    # --------------------------------------------
    print("Elementy krotki:")
    for element in dane:
        print(element)

    # --------------------------------------------
    # ZMIANA ELEMENTU – NIE DZIAŁA
    # --------------------------------------------
    # dane[0] = 10   # ❌ błąd
    #
    # Krotki nie można bezpośrednio zmieniać

    # --------------------------------------------
    # JAK ZMIENIĆ DANE W KROTCE?
    # --------------------------------------------
    # Nie zmieniamy starej krotki.
    # Tworzymy nową krotkę:
    # 1. zamieniamy krotkę na listę
    # 2. modyfikujemy listę
    # 3. zamieniamy ją z powrotem na krotkę
    lista_pomocnicza = list(dane)
    lista_pomocnicza.append(4)
    dane = tuple(lista_pomocnicza)
    print("Nowa krotka po konwersji:", dane)


    print("\n=== SŁOWNIK ===")

    # ============================================
    # SŁOWNIK – DANE W FORMIE KLUCZ : WARTOŚĆ
    # ============================================
    # Słownik przechowuje dane opisane nazwami
    #
    # Przykład:
    # "imie"  -> "Jan"
    # "wiek"  -> 16
    # "klasa" -> "1A"
    #
    # W słowniku nie odwołujemy się do indeksów,
    # tylko do kluczy
    #
    # WAŻNE:
    # Klucze w słowniku powinny być unikalne
    # ============================================

    uczen = {
        "imie": "Jan",
        "wiek": 16,
        "klasa": "1A"
    }

    print("Słownik:", uczen)

    # --------------------------------------------
    # ODCZYT DANYCH
    # --------------------------------------------
    print("Imię:", uczen["imie"])

    # --------------------------------------------
    # BEZPIECZNIEJSZY ODCZYT
    # --------------------------------------------
    # get() nie zgłasza błędu, jeśli klucza nie ma
    print("Miasto:", uczen.get("miasto"))  # tutaj jeszcze nie istnieje

    # --------------------------------------------
    # ZMIANA WARTOŚCI
    # --------------------------------------------
    uczen["wiek"] = 17

    # --------------------------------------------
    # DODAWANIE NOWEGO ELEMENTU
    # --------------------------------------------
    uczen["miasto"] = "Gdańsk"
    print("Po zmianach:", uczen)

    # --------------------------------------------
    # USUWANIE ELEMENTU
    # --------------------------------------------
    del uczen["klasa"]
    print("Po usunięciu klucza 'klasa':", uczen)

    # --------------------------------------------
    # WYSZUKIWANIE KLUCZA
    # --------------------------------------------
    if "imie" in uczen:
        print("Klucz 'imie' istnieje")
    else:
        print("Klucz 'imie' nie istnieje")

    # --------------------------------------------
    # WYSZUKIWANIE WARTOŚCI
    # --------------------------------------------
    if 17 in uczen.values():
        print("Wartość 17 istnieje w słowniku")
    else:
        print("Wartości 17 nie ma w słowniku")

    # --------------------------------------------
    # DŁUGOŚĆ SŁOWNIKA
    # --------------------------------------------
    print("Ilość elementów w słowniku:", len(uczen))

    # --------------------------------------------
    # PĘTLA PO SŁOWNIKU
    # --------------------------------------------
    print("Elementy słownika:")
    for klucz in uczen:
        print(klucz, ":", uczen[klucz])

    # --------------------------------------------
    # KLUCZE I WARTOŚCI OSOBNO
    # --------------------------------------------
    # list() zamienia wynik na zwykłą listę,
    # żeby był czytelniejszy przy wyświetlaniu
    print("Klucze:", list(uczen.keys()))
    print("Wartości:", list(uczen.values()))

    # --------------------------------------------
    # PARY KLUCZ : WARTOŚĆ
    # --------------------------------------------
    print("Pary klucz : wartość")
    for klucz, wartosc in uczen.items():
        print(klucz, ":", wartosc)

    # --------------------------------------------
    # USUWANIE WSZYSTKICH ELEMENTÓW
    # --------------------------------------------
    # clear() usuwa wszystkie elementy słownika
    przyklad = {"a": 1, "b": 2}
    przyklad.clear()
    print("Słownik po clear():", przyklad)


# Uruchomienie funkcji
struktury_danych()