# L10 - Le strutture dati (parte 1)
# Liste, Tuple, Set, Dizionari
# Le tuple sono simili alle liste, ma sono IMMUTABILI.
# Questo significa che una volta creata, una tupla non può essere modificata.
# I set sono insiemi, quindi non contengono elementi duplicati e non sono ordinati.
# I dizionari sono collezioni di coppie chiave-valore.

dizionario_di_esempio = {
    "nome": "Mario",
    "cognome": "Rossi",
    "età": 30,
    "numeri_di_telefono": ["123456789", "987654321"],
    "indirizzo": {
        "via": "Via Roma",
        "numero": 10
    }
}

# LE LISTE

# Le liste sono una delle strutture dati più utilizzate in Python.
# Sono sequenze ordinate di elementi, che possono essere di qualsiasi tipo.

# Creazione di una lista
# Per creare una lista, si utilizzano le parentesi quadre [].
# Gli elementi della lista sono separati da virgole.
lista = [1, 2, 3, 4, 5]
print(lista)  # Output: [1, 2, 3, 4, 5]

# Le liste possono contenere elementi di diversi tipi.
lista = [1, "due", 3.0, True]
print(lista)  # Output: [1, 'due', 3.0, True]

# Le liste possono anche contenere altre liste.
lista = [[1, 2], [3, 4], [5, 6]]
print(lista)  # Output: [[1, 2], [3, 4], [5, 6]]

# Creazione di una lista vuota
# Per creare una lista vuota, si utilizzano le parentesi quadre senza elementi.
lista_vuota = []
print(lista_vuota)  # Output: []

# Accesso agli elementi di una lista
# Si può accedere agli elementi di una lista utilizzando l'INDICE.
# L'indice di un elemento è la sua posizione all'interno della lista.
# Gli indici delle liste in Python partono da 0.
lista = [10, 20, 30, 40, 50]
print(lista[0])  # Output: 10
print(lista[1])  # Output: 20

# Gli indici negativi permettono di accedere agli elementi partendo dalla fine della lista.
# L'indice -1 corrisponde all'ultimo elemento della lista.
print(lista[-1])  # Output: 50
print(lista[-2])  # Output: 40

indice = 2
print(lista[indice]) # Output: 30

# È come se dentro la lista ci fossero delle variabili ottenute tramite l'indice
# lista = [lista[0] = 10, lista[1] = 20, lista[2] = 30, lista[3] = 40, lista[4] = 50]

# Modifica degli elementi di una lista
# Gli elementi di una lista possono essere modificati assegnando un nuovo valore all'elemento.
lista = [10, 20, 30, 40, 50]
lista[0] = 100
print(lista)  # Output: [100, 20, 30, 40, 50]
lista[indice] = 300

# Aggiunta di elementi a una lista
# Per aggiungere un elemento alla fine di una lista, si utilizza il metodo append().
lista = [10, 20, 30]
lista.append(40)
print(lista)  # Output: [10, 20, 30, 40]

# Per aggiungere più elementi alla fine di una lista, si utilizza il metodo extend().
lista = [10, 20, 30]
lista.extend([40, 50])
print(lista)  # Output: [10, 20, 30, 40, 50]

# Per aggiungere un elemento in una posizione specifica di una lista, si utilizza il metodo insert().
lista = [10, 20, 30]
lista.insert(1, 15)
print(lista)  # Output: [10, 15, 20, 30]

# Rimozione di elementi da una lista
# Per rimuovere un elemento da una lista, si utilizza il metodo remove().
lista = [10, 20, 30, 30, 50]
lista.remove(30)
print(lista)  # Output: [10, 20, 30, 50]

# Per rimuovere un elemento in una posizione specifica di una lista, si utilizza il metodo pop().
lista = [10, 20, 30, 40, 50]
elemento_rimosso = lista.pop(2)
print(lista)  # Output: [10, 20, 40, 50]
print(elemento_rimosso)  # Output: 30

lista.pop()  # Rimuove l'ultimo elemento della lista
# Equivalente a lista.pop(-1)

# Per rimuovere tutti gli elementi da una lista, si utilizza il metodo clear().
lista = [10, 20, 30, 40, 50]
lista.clear()
print(lista)  # Output: []

# Altri metodi delle liste
# Altri metodi utili delle liste sono:
# - index(): restituisce l'indice di un elemento specifico.
# - count(): restituisce il numero di occorrenze di un elemento.
# - reverse(): inverte l'ordine degli elementi della lista.
# - copy(): crea una copia della lista.
lista = [10, 20, 30, 20, 40, 50]
print(lista.index(20))  # Output: 1
print(lista.count(20))  # Output: 2
lista.reverse()
print(lista)  # Output: [50, 40, 20, 30, 20, 10]
copia_lista = lista.copy()
print(copia_lista)  # Output: [50, 40, 20, 30, 20, 10]

# Funzione built-in len()
# La funzione len() restituisce la lunghezza di una lista, cioè il numero di elementi che contiene.
lista = [10, 20, 30, 40, 50]
lunghezza = len(lista)
print(lunghezza)  # Output: 5
ultimo_indice = len(lista) - 1