<jupyter_start><jupyter_text>Liste 3 - Metodi [Scarica zip esercizi](../_static/generated/lists.zip)[Naviga file online](https://github.com/DavidLeoni/softpython-it/tree/master/lists) Le liste sono oggetti di tipo `list` e possiedono dei metodi che permettono di operare su di essi:|Metodo|Ritorna|Descrizione||-------|------|-----------||[list.append(obj)](Metodo-append)|`None`|Aggiunge un nuovo elemento alla fine della lista||[list.extend(list)](Metodo-extend)|`None`|Aggiunge diversi nuovi elementi alla fine della lista||[list.insert(int,obj)](Metodo-insert)|`None`|Aggiunge un nuovo elemento a qualche posizione data||[list.pop()](Metodo-pop)|obj|Rimuove e ritorna l'elemento all'ultima posizione||[list.pop(int)](Metodo-pop)|obj|Dato un indice, rimuove e ritorna l'elemento a quella posizione||[list.reverse()](Metodo-reverse)|`None`|Inverte l'ordine degli elementi||[list.sort()](Metodo-sort)|`None`|Ordina gli elementi||[string_sep.join(seq)](Metodo-join---da-liste-a-stringhe)|`string`|produce una stringa concatenando tutti gli elementi in seq separati da string_sep|  **ATTENZIONE: I METODI DELLE LISTE _MODIFICANO_ LA LISTA SU CUI VENGONO CHIAMATI !**Quando chiami un metodo di una lista (l'oggetto a sinistra del punto `.`), MODIFICHI la lista stessa (diversamente dai metodi sulle stringhe che generano sempre una nuova stringa senza cambiare l'originale)**ATTENZIONE: I METODI DELLE LISTE _NON_ RITORNANO NULLA!**Quasi sempre ritornano l'oggetto `None` (diversamente da quelli delle stringhe che ritornano sempre una nuova stringa)  Metodi di ricercaLe liste mettono a disposizione diversi metodi per effettuare ricerche e trasformazioni al loro interno, ma attenzione: il potere è nulla senza il controllo! Spesso ti troverai con l'esigenza di usarli, e potrebbero anche funzionare con qualche piccolo esempio, ma molto spesso nascondono tranelli che poi si rimpiangono amaramente. Quindi quando scrivi codice con uno di questi metodi, **poniti sempre le domande che evidenzieremo!**    |Metodo|Ritorna|Descrizione||-------|------|-----------||[str1.split(str2)](Metodo-split---da-stringhe-a-liste)|`list`|Produce una lista con tutte le parole in str1 separate da str2| |[list.count(obj)](Metodo-count)|`int`|Conta le occorrenze di un elemento||[list.index(obj)](Metodo-index)|`int`|Trova la prima occorrenza di un elemento e ne ritorna la posizione||[list.remove(obj)](Metodo-remove)|`None`|Rimuove la prima occorrenza di un elemento|  Che fare- scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere: ```lists    lists1.ipynb    lists1-sol.ipynb             lists2.ipynb    lists2-sol.ipynb             lists3.ipynb    lists3-sol.ipynb             lists4.ipynb    lists4-sol.ipynb             jupman.py         ```**ATTENZIONE**: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.- apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook `lists3.ipynb`- Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte **ESERCIZIO**, che ti chiederanno di scrivere dei comandi Python nelle celle successive. Gli esercizi sono graduati per difficoltà, da una stellina ✪ a quattro ✪✪✪✪Scorciatoie da tastiera:* Per eseguire il codice Python dentro una cella di Jupyter, premi `Control+Invio`* Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi `Shift+Invio`* Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi `Alt+Invio`* Se per caso il Notebook sembra inchiodato, prova a selezionare `Kernel -> Restart`  Metodo appendPossiamo MODIFICARE una lista aggiungendo un elemento alla volta usando il metodo `append`.Supponiamo di partire da una lista vuota:<jupyter_code>la = []<jupyter_output><empty_output><jupyter_text>Se vogliamo aggiungere come elemento il numero `57`, possiamo scrivere così:<jupyter_code>la.append(57)<jupyter_output><empty_output><jupyter_text>Notiamo che la lista che abbiamo creato inizialmente risulta MODIFICATA:<jupyter_code>la<jupyter_output><empty_output><jupyter_text>**ATTENZIONE:** `la.append(57)` **non ha restituito NULLA !!!!**    Guarda bene l'output della cella con l'istruzione `la.append(57)`, noterai che non c'è proprio niente. Questo perchè lo scopo di `append` è MODIFICARE la lista su cui viene chiamato, NON generare nuove liste.  Aggiungiamo un'altro numero _alla fine_ della lista:<jupyter_code>la.append(96)
la
la.append(74)
la<jupyter_output><empty_output><jupyter_text>Riguardiamoci cosa è successo in Python Tutor:<jupyter_code># AFFINCHE' PYTHON TUTOR FUNZIONI, RICORDATI DI ESEGUIRE QUESTA CELLA con Shift+Invio
#   (basta eseguirla una volta sola, la trovi anche all'inizio di ogni foglio)

import sys
sys.path.append('../')
import jupman
la = []
la.append(57)
la.append(96)
la.append(74)

jupman.pytut()<jupyter_output><empty_output><jupyter_text>Nota come ad espandersi sia sempre la stessa zona di memoria gialla associata alla variabile `la`. Abbiamo detto che il metodo `append` non ritorna nulla, cerchiamo di specificare meglio. Nella tabella dei metodi, è presente una colonna chiamata _Ritorna_. Se vai a vedere, per quasi tutti i metodi incluso `append` è indicato che viene ritornato `None`. `None` è l'oggetto più noioso di Python, perchè letteralmente significa niente. Cosa si può fare con niente? Ben poco, così poco che Jupyter quando si ritrova come risultato un oggetto `None` non lo stampa nemmeno. Proviamo a inserire direttamente `None` in una cella, vedrai che non verrà riportato nell'output della cella:<jupyter_code>None<jupyter_output><empty_output><jupyter_text>Un modo per forzare la stampa è usare il comando `print`:<jupyter_code>print(None)<jupyter_output>None<jupyter_text>**ESERCIZIO**: Qual'è il tipo dell'oggetto `None`?  Scoprilo usando la funzione `type`<jupyter_code># scrivi qui

#type(None)<jupyter_output><empty_output><jupyter_text>Proviamo a ripetere cosa succede con `append`. Se chiami il metodo `append` su una lista, `append` MODIFICA silenziosamente la lista, e RITORNA come risultato di essere stato chiamato l'oggetto `None`. Dato che Jupyter ritiene questo oggetto non interessante, non lo stampa nemmeno come risultato. Cerchiamo di esplicitare meglio questo misterioso `None`. Se è vero che `append` lo produce come risultato di essere chiamato, vuol dire che possiamo associare questo risultato a qualche variabile. Proviamo ad associarlo alla variabile `x`:<jupyter_code>la = []
x = la.append(78)<jupyter_output><empty_output><jupyter_text>Ora, se tutto è andato come abbiamo scritto, `append` dovrebbe aver modificato la lista:<jupyter_code>la<jupyter_output><empty_output><jupyter_text>e alla variabile `x` dovrebbe essere associato `None`. Quindi, se chiediamo a Jupyter di mostrare il valore associato ad `x` e se quel valore è `None`, non dovremmo vedere nulla:<jupyter_code>x<jupyter_output><empty_output><jupyter_text>notiamo che non c'è nessun output nella cella, pare che siamo davvero in presenza di `None`. Forziamo la stampa con il comando `print`:<jupyter_code>print(x)<jupyter_output>None<jupyter_text>Eccolo ! Probabilmente sarai un po' confuso da tutto ciò, quindi proviamo a rivedere bene che succede in Python Tutor:<jupyter_code>la = []
x = la.append(78)
print("la è", la)
print("x è ", x)

jupman.pytut()<jupyter_output>la è [78]
x è  None<jupyter_text>Qual'è il succo di tutto questo discorso? **RIUSARE IL RISULTATO DI CHIAMATE AI METODI DELLE LISTE E' QUASI SEMPRE UN ERRORE !!!!**Dato che chiamare i metodi delle lista ci ritorna `None`, che è un oggetto 'inutile', tentare di riusarlo produrrà quasi sicuramente un errore **ESERCIZIO**: Costruisci una lista aggiungendo un elemento alla volta con il metodo `append`. Aggiungi gli elementi `77`, `"prova"`, `[60,93]` con tre chiamate ad `append`, ed infine stampa la lista.Dopo il tuo codice, dovresti vedere `[77, 'prova', [60, 93]]`<jupyter_code>la = []

# scrivi qui
la.append(77)
la.append("prova")
la.append([60, 93])

#print(la)<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Il codice seguente:```pythonla = []la.append(85,70,94)```1. produce un errore (quale?)2. modifica la lista (come?) **RISPOSTA**: la 1: `append` accetta un solo argomento, passandone di più produrrà un errore, prova ad eseguire il codice in una cella per vedere quale. **DOMANDA**: Il codice seguente```pythonla = []la.append(87).append(96)```1. produce un errore2. aggiunge a `la` i numeri `87` e `96` **RISPOSTA**: la 1: produce un errore, perchè come abbiamo detto la chiamata ad `la.append(87)` MODIFICA la lista `la` su cui è chiamato e ritorna il valore `None`. Se su `None` proviamo a chiamare `.append(96)`, visto che `None` non è una lista otterremo un messaggio di errore. Sincerati di questo usando Python Tutor. **DOMANDA**: torniamo brevemente alle stringhe. Guarda il codice seguente (se non ti ricordi cosa fanno i metodi delle stringhe [guarda qua](https://it.softpython.org/strings/strings3-sol.htmlMetodi)):    ```pythonsa = '    trento    'sb = sa.strip().capitalize()print(sb)```1. produce un errore (quale?)2. cambia `sa` (come?)3. stampa qualcosa (cosa?) **RISPOSTA**: La 3: stampa `Trento`. Diversamente dalle liste, le stringhe sono sequenze _immutabili_: significa che quando chiami un metodo sulle stringhe sei sicuro che RESTITUIRA' una stringa NUOVA.  Quindi la prima chiamata a `sa.strip()` RESTITUISCE la stringa senza spazi all'inizio e alla fine `'trento'`, e su questa stringa viene chiamato il metodo `capitalize()` che rende il primo carattere maiuscolo. Se questo non ti è chiaro, prova ad eseguire il codice seguente in Python Tutor. E' equivalente a quello dell'esempio ma esplicita il passaggio assegnando alla variabile extra `x`. il risultato della chiamata a `sa.strip()` ```pythonsa = '    trento    'x = sa.strip()sb = x.capitalize()print(sb)``` **DOMANDA**: Guarda questo codice. Stamperà qualcosa alla fine? O produrrà un errore?    ```pythonla = []lb = []la.append(lb)lb.append(98)lb.append(77)print(la)``` **RISPOSTA**: Stamperà `[[98, 77]]`, perchè abbiamo messo `lb` dentro `la`. Anche se con la prima `append` abbiamo inserito `lb` come primo elemento di `la`, dopo è perfettamente lecito continuare a modificare `lb` chiamando `lb.append(98)`. Prova ad eseguire il codice in Python Tutor, e guarda le frecce.  Esercizio - accrescere una lista 1Data la lista `la` di _dimensione fissa 7_, scrivi del codice per crescere la lista vuota `lb` così che contenga _solo_ gli elementi di `la` a indici pari (0, 2, 4, ...). - Il tuo codice dovrebbe funzionare per qualunque lista `la` di dimensione fissa 7```python   0 1 2 3 4 5 6  la=[8,4,3,5,7,3,5]lb=[]```Dopo il tuo codice, dovresti ottenere:```python>>> print(lb)[8,3,7,5]```<jupyter_code>#   0 1 2 3 4 5 6  
la=[8,4,3,5,7,3,5]
lb=[]

# scrivi qui
lb.append(la[0])
lb.append(la[2])
lb.append(la[4])
lb.append(la[6])
print(lb)<jupyter_output>[8, 3, 7, 5]<jupyter_text>Metodo extend Prima con `append` abbiamo visto come accrescere una lista _un elemento alla volta_. E se volessimo aggiungere in un colpo solo parecchi elementi, magari presi da un'altra lista? Come potremmo fare? Dovremmo usare il metodo `extend`, che MODIFICA la lista su cui è chiamato aggiungendo tutti gli elementi trovati nella sequenza presa in input.<jupyter_code>la = [78,60,59]
lb = [68,97,67,98]
la.extend(lb)
la
lb<jupyter_output><empty_output><jupyter_text>Nell'esempio qua sopra, `extend` è chiamato sulla variabile `la`, e come parametro gli abbiamo passato `lb`**ATTENZIONE**: `la` è MODIFICATA, invece la sequenza che gli abbiamo passato tra le parentesi tonde no (`lb` nell'esempio)! **DOMANDA**: l'esecuzione del metodo `extend` ritorna qualcosa? Cosa vedi nell'output della cella `la.extend(lb)` ? **RISPOSTA**:  `extend`, come quasi tutti i metodi delle liste, non ritorna nulla, o meglio, ritorna il poco utile oggetto `None`, che non viene nemmeno stampato da Jupyter.  Verifichiamo meglio cosa è successo con Python Tutor:<jupyter_code>la = [78,60,59]
lb = [68,97,67,98]
la.extend(lb)

jupman.pytut()<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda questo codice. Quali saranno i valori associati alle variabili `la` ,`lb` e `x` dopo la sua esecuzione?```pythonla = [34,79,54]lb = [86,45]x = la.extend(lb)print('la è ', la)print('lb è ', lb)print('x è ', x)``` **RISPOSTA**: Verrà stampato questo:```la è  [34, 79, 54, 86, 45]lb è  [86, 45]x è  None``` `la` è stata MODIFICATA aggiungendo tutti gli elementi di `lb`. La chiamata ad `extend`, come quasi tutti i metodi delle liste, ha ritornano l'oggetto `None` che è stato associato alla variabile `x`. Cerca di capire bene cosa è successo usando Python Tutor.   Estendere con sequenzeAbbiamo detto che tra le parentesi tonde `extend` può prendere una sequenza generica, non solo liste. Questo vuol dire che possiamo anche passargli una stringa. Per esempio:<jupyter_code>la = [78,65,87]

s = "ciao"

la.extend(s)
la<jupyter_output><empty_output><jupyter_text>Dato che stringa è una sequenza di caratteri, `extend` ha preso ciascuno di questi elementi e li ha aggiunti a `la` **DOMANDA**: il valore associato alla variabile `s` è stato modificato? **RISPOSTA**: assolutamente impossibile, perchè a) `extend` modifica solo la lista su cui è chiamato e b) le stringhe sono comunque immutabili. **DOMANDA**: Il codice seguente:```pythonla = [78,65]la.extend(68,85,87)```1. produce un errore (quale?) 2. modifica `la` (come?) **RISPOSTA**: La 1: produce un errore, perchè ad `extend` dobbiamo passare UN parametro solo, che deve essere _una sequenza_. Qua invece stiamo passando tanti parametri. Un'alternativa potrebbe essere costruire una lista così:```pythonla = [78,65]la.extend([68,85,87])``` **DOMANDA**: Se questo codice viene eseguito, che succede?```pythonsa = "ciao"sb = "mondo"sa.extend(sb)```1. `sa` viene modificata (come?)2. otteniamo un errore (quale?) **RISPOSTA**: la 2: otteniamo un errore, perchè `extend` è un metodo esclusivo delle liste. Appartiene solo alle liste perchè MODIFICA l'oggetto su cui è chiamato - dato che le stringhe sono oggetti immutabili, non avrebbe senso estenderle. **DOMANDA**: Se questo codice viene eseguito, che succede?```pythonla = [1,2,3]lb = [4,5]lc = [6,7,8]la.extend(lb).extend(lc)```1. `la` diventa `[1,2,3,4,5,6,7,8]`2. un errore (quale?)3. `la` diventa `[1,2,3,4,5]` e un errore(quale?) **RISPOSTA**: la 3: `la` diventa `[1,2,3,4,5]` e subito dopo otteniamo un errore, perchè la chiamata a `la.extend(lb)` MODIFICA `la` a `[1,2,3,4,5]` e RITORNA il valore `None`. A quel punto, Python cerca di chiamare il metodo `extend` sull'oggetto `None`, ma non essendo una lista, ci becchiamo questo errore (**per convincerti, verifica il tutto il Python Tutor** !!!)```python---------------------------------------------------------------------------AttributeError                            Traceback (most recent call last) in       3 lc = [6,7,8]      4 ----> 5 la.extend(lb).extend(lc)AttributeError: 'NoneType' object has no attribute 'extend'```  Esercizio: accrescere una lista 2 Date due _liste_ `la` ed `lb` e un elemento `x`, scrivi del codice che MODIFICA `la` in modo che `la` contenga alla fine l'elemento `x` seguito da tutti gli elementi di `lb`- **NOTA 1**: il tuo codice dovrebbe funzionare con qualunque `la` ed `lb`- **NOTA 2**: `id` è una funzione di Python che associa ad ogni regione di memoria un identificativo numerico univoco. Se provi a stampare `id(la)` _prima_ di modificare `la` e `id(la)` dopo, dovresti ottenere _esattamente_ lo stesso id. Se ne ottieni uno diverso, significa che hai generato una lista interamente nuova. In ogni caso, verifica che funzioni in Python Tutor.```pythonla = [5,9,2,4]lb = [7,1,3]x = 8```Dovresti ottenere:```python>>> print(la)[5,9,2,4,8,7,1,3]>>> print(lb)[7,1,3]>>> print(x)8```<jupyter_code>la = [5,9,2,4]
lb = [7,1,3]
x = 8

# scrivi qui
la.append(x)
la.extend(lb)
#print(la)
#print(lb)
#print(x)<jupyter_output><empty_output><jupyter_text>Esercizio - zsliceScrivi del codice che date due liste `la` (di almeno 3 elementi) e `lb`,  MODIFICA `lb` in modo che vi siano aggiunti i primi 3 elementi di `la` seguiti dagli ultimi 3 elementi di `la`* il tuo codice deve funzionare con qualsiasi lista * usa `extend` e le slice```pythonla = ['a','b','c','d','e','f','g','h','i','l','m','n','o']lb = ['z']```Dovresti ottenere:```python>>> print(la)['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l', 'm', 'n', 'o']>>> print(lb)['z', 'a', 'b', 'c', 'm', 'n', 'o']```<jupyter_code>la = ['a','b','c','d','e','f','g','h','i','l','m','n','o']
lb = ['z']

# scrivi qui

lb.extend(la[:3])  # una slice genera una lista
lb.extend(la[-3:])

#print(la)
#print(lb)<jupyter_output><empty_output><jupyter_text>Esercizio - vedunazeblagScrivi del codice che data una lista di tre stringhe `parole` e una lista vuota `la`, riempie `la` con tutti i primi 3 caratteri di ogni stringa in `parole`. * il tuo codice deve funzionare con qualsiasi lista di 3 stringhe* usa le sliceEsempio - data:```pythonparole = ["vedo", "una", "zebra", "laggiù"]la = []```il tuo codice deve mostrare```python>>> print(t)['v', 'e', 'd', 'u', 'n', 'a', 'z', 'e', 'b', 'l', 'a', 'g']```<jupyter_code>parole = ["vedo", "una", "zebra", "laggiù"]

la = []

# scrivi qui
la.extend(parole[0][:3])
la.extend(parole[1][:3])
la.extend(parole[2][:3])
la.extend(parole[3][:3])
print(la)<jupyter_output>['v', 'e', 'd', 'u', 'n', 'a', 'z', 'e', 'b', 'l', 'a', 'g']<jupyter_text>Metodo insert`insert` MODIFICA la lista inserendo un elemento ad uno specifico indice - tutti gli elementi a partire da quell'indice vengono spostati in avanti di una posizione<jupyter_code>#0 1 2 3
la = [6,7,8,9]
la.insert(2,55)  # inserisce il numero 55 all'indice 2
la
la.insert(0,77)  # inserisce il numero 77 all'indice 0
la<jupyter_output><empty_output><jupyter_text>Possiamo inserire dopo la fine:<jupyter_code>la.insert(6,88)  # inserisce il numero 88 all'indice 6
la<jupyter_output><empty_output><jupyter_text>Nota che se sforiamo con l'indice, l'elemento viene comunque messo alla fine e non vengono create celle vuote:<jupyter_code>la.insert(1000,99)  # in questo caso inserisce il numero 99 all'indice 7<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Data una lista qualsiasi `x`, questo codice cosa produce? Possiamo riscriverlo in un'altra maniera?```pythonx.insert(len(x),66)```1. produce una nuova lista (quale?)2. modifica `x` (come?)3. un errore **RISPOSTA**: La 2 - il codice MODIFICA la lista `x` aggiungendo alla lista l'elemento `66` alla fine. Il codice è pertanto equivalente al codice ```pythonx.append(66)``` **DOMANDA**: Il seguente codice, cosa produce?```pythonla = [3,4,5,6]la.insert(0,[1,2])print(la)```1. stampa [1,2,3,4,5,6]2. un errore (quale?)3. qualcos'altro (cosa?) **RISPOSTA**: La 3 - il codice inserisce come zeresimo elemento di `la` la lista `[1,2]`. La stampa produrrà quindi `[[1, 2], 3, 4, 5, 6]`  **DOMANDA**: Il seguente codice cosa produce?```pythonla = [4,5,6]la.insert(0,1,2,3)print(la)```1. stampa `[1,2,3,4,5,6]`2. un errore (quale?)3. qualcos'altro (cosa?) **RISPOSTA**: La 2 - un errore, a `insert` possiamo passare solo 2 parametri, l'indice di inserimento e il singolo oggetto da inserire **DOMANDA**: Il seguente codice cosa produce?```pythonla = [4,5,6]lb = la.insert(0,3)lc = lb.insert(0,2)ld = lc.insert(0,1)print(ld)```1. stampa `[1,2,3,4,5,6]`2. un errore (quale?)3. qualcos'altro (cosa?) **RISPOSTA**: la 2 - un errore: come quasi tutti i metodi delle liste, `insert` ritorna `None`, quindi scrivendo `lb = la.insert(0,3)` andiamo ad associare `None` a `lb`, e quando nella riga successiva Python incontra `lc = lb.insert(0,2)` e prova ad eseguire `None.insert(0,2)` si lamenterà perchè `None` non essendo una lista non ha il metodo `insert`.  Esercizio - insertandoData la lista:`la = [7,6,8,5,6]`scrivi del codice che la MODIFICA usando solo chiamate a `insert`. Dopo il tuo codice, `la` deve apparire così:```python>>> print(la)[7, 77, 99, 6, 8, 88, 5, 6, 55]```<jupyter_code>la = [7,6,8,5,6]

# scrivi qui

la.insert(3,88)
la.insert(1,99)
la.insert(1,77)
la.insert(len(la),55)

#print(la)<jupyter_output><empty_output><jupyter_text>**ATTENZIONE**: chiamare `insert` è molto più lento di `append` !!Una chiamata ad `insert` riscrive tutte le celle successive a quella dell'inserimento, mentre invece `append` aggiunge una cella e basta. Dato che il computer è veloce, molto spesso non ci si accorge della differenza, ma quando possibile, e specialemente se devi scrivere programmi che operano su grandi quantità di dati, prova a scrivere il codice usando `append` invece di `insert`.  Esercizio - insappendQuesto codice prende come input una lista vuota `la` e una lista di numeri `lb`. Cerca di capire cosa fa, e riscrivilo usando degli `append`.<jupyter_code>la = []
lb = [7,6,9,8]
la.insert(0,lb[0]*2)
la.insert(0,lb[1]*2)
la.insert(0,lb[2]*2)
la.insert(0,lb[3]*2)
print(la)
la = []
lb = [7,6,9,8]

# scrivi qui
la.append(lb[-1]*2)
la.append(lb[-2]*2)
la.append(lb[-3]*2)
la.append(lb[-4]*2)
#print(la)<jupyter_output><empty_output><jupyter_text>Metodo popIl metodo `pop` se chiamato senza argomenti rimuove l'ultimo elemento (MODIFICANDO la lista) e lo ritorna:<jupyter_code>cesta = ['melone','fragola', 'anguria']
cesta.pop()
cesta
cesta.pop()
cesta<jupyter_output><empty_output><jupyter_text>Visto che l'ultimo elemento è _ritornato_ dalla `pop`, possiamo assegnarlo ad una variabile:<jupyter_code>frutto = cesta.pop()<jupyter_output><empty_output><jupyter_text>Nota che non vediamo più nessun risultato stampato perchè l'elemento ritornato è stato assegnato alla variabile `frutto`:<jupyter_code>frutto<jupyter_output><empty_output><jupyter_text>Constatiamo anche che `cesta` è stata MODIFICATA:<jupyter_code>cesta<jupyter_output><empty_output><jupyter_text>Chiamare ulteriormente `pop` su una lista vuota genera un'errore: ```pythoncesta.pop()---------------------------------------------------------------------------IndexError                                Traceback (most recent call last) in ()----> 1 cesta.pop()IndexError: pop from empty list``` Opzionalmente, per rimuovere un elemento ad una specifica posizione possiamo passare a `pop` un indice da 0 INCLUSO alla lunghezza della lista ESCLUSA:<jupyter_code>#           0           1             2        3
attrezzi = ['martello', 'cacciavite', 'pinza', 'martello']
attrezzi.pop(2)
attrezzi<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda i frammenti di codice seguenti, e per ciascuno cerca di indovinare che risultato produce (o se risulta in un errore).1.  ```python    la = ['a']    print(la.pop())    print(la.pop())    ```1.  ```python    la = [4,3,2,1]    print(la.pop(4))    print(la)    ```1.  ```python    la = [1,2,3,4]    print(la.pop(3))    print(la)    ```    1.  ```python    la = [1,2,3,4]    print(la.pop(-1))    print(la)    ```1.  ```python    s = 'grezzo'    print(s.pop())    print(s)    ```1.  ```python    la = ['molto', 'grezzo']    print(la.pop())    print(la)    ```1.  ```python    la = ['a', ['a']]    print(la.pop())    print(la)    ```  Esercizio - popcornData una lista `corn` di esattamente 4 caratteri, scrivi del codice che trasferisce in ordine inverso tutti i caratteri da `corn` ad un'altra lista `scatola` che inizialmente è vuota.- **NON** usare metodi come `reverse` o funzioni come `reversed`- Il tuo codice deve funzionare con _qualsiasi_ lista `corn` di 4 elementi Esempio - date:```pythoncorn = ['t','o','r','o']scatola = []```dopo il tuo codice, deve risultare:```python>>> print(corn)[]>>> print(scatola)['o','r','o','t']```<jupyter_code>corn = ['t','o','r','o']
scatola = []

# scrivi qui

scatola.append(corn.pop())
scatola.append(corn.pop())
scatola.append(corn.pop())
scatola.append(corn.pop())
print(scatola)<jupyter_output>['o', 'r', 'o', 't']<jupyter_text>Esercizio - zonzo Data una lista `la` contenente dei caratteri, e una lista `lb` contente esattamente due posizioni  _ordinate in modo crescente_ , scrivi del codice che elimina da `la` i caratteri alle posizioni specificate in `lb`. * **ATTENZIONE**: chiamando la `pop` la prima volta MODIFICHERAI `la`, quindi l'indice del secondo elemento da eliminare andrà opportunamente aggiustato !* **NON** creare nuove liste, quindi niente righe che iniziano con `la = `* Il tuo codice deve funzionare per _qualsiasi_ `la`,  e _qualsiasi_ `lb` da due elementiEsempio - dati:```python      0   1   2   3   4la = ['z','o','n','z','o']lb = [2,4]```alla posizione 2 in `la` troviamo la `n` e alla 4 la `o`, quindi dopo il tuo codice dovrà risultare:```python>>> print(la)['z', 'o', 'z']```<jupyter_code>#      0   1   2   3   4
la = ['z','o','n','z','o']
lb = [2,4]

# scrivi qui
la.pop(lb[0])
la.pop(lb[1]-1)
#print(la)<jupyter_output><empty_output><jupyter_text>Metodo reverseIl metodo `reverse` MODIFICA la lista su cui è chiamato invertendo l'ordine degli elementi.Vediamo un esempio:<jupyter_code>la = [7,6,8,4]
la.reverse()
la<jupyter_output><empty_output><jupyter_text>**ATTENZIONE**: `reverse` **NON RITORNA NULLA!**Per essere precisi, ritorna `None`<jupyter_code>lb = [7,6,8,4]
x = lb.reverse()
print(x)
print(lb)<jupyter_output>[4, 8, 6, 7]<jupyter_text>**DOMANDA**: Il codice seguente che effetto produce?```pythons = "transatlantico"s.reverse()print(s)```1. un errore (quale?)2. stampa la stringa rovesciata  **RISPOSTA**: `.reverse()` è un metodo presente SOLO nelle LISTE, quindi usandolo sulle stringhe stringhe si otterrà un errore. E c'è da attenderselo, visto che `reverse` MODIFICA l'oggetto su cui è chiamato e perchè le stringhe sono _immutabili_ nessun metodo delle stringhe può modificare la stringa su cui è chiamato. **DOMANDA**: Se `x` è una lista qualsiasi, che effetto produce il codice seguente?```pythonx.reverse().reverse()```1. cambia la lista (come?)2. non cambia la lista2. genera un errore (quale?) **RISPOSTA**: La 3 - genera un errore, perchè `reverse()` ritorna `None` e `None` non essendo una lista non ha il metodo `reverse()`.  Esercizio - come va?Scrivi del codice che date due liste `la` e `lb`, MODIFICA `la` aggiungendogli tutti gli elementi di `lb` e rovesciando poi l'intera lista. * il tuo codice deve funzionare per qualunque `la` e `lb`* **NON** modificare `lb`Esempio - dati: ```pythonla = ['c','o','m','e']lb = ['v','a','?']```Dopo il tuo codice, deve stampare:```python>>> print('la=',la)la= ['?', 'a', 'v', 'e', 'm', 'o', 'c']>>> print('lb=',lb)lb= ['v', 'a', '?']```<jupyter_code>la = ['c','o','m','e']
lb = ['v','a','?']

# scrivi qui
la.extend(lb)
la.reverse()
#print('la=',la)
#print('lb=',lb)<jupyter_output><empty_output><jupyter_text>Esercizio - cose prezioseDate due liste `la` e `lb`, scrivi del codice che STAMPA una lista con gli elementi di `la` e `lb` in ordine invertito- **NON** modificare `la` e **NON** modificare `lb`- il tuo codice deve funzionare per qualsiasi lista `la` e `lb`Esempio - dati```pythonla = ['c', 'o', 's', 'e']lb = ['p', 'r', 'e', 'z', 'i', 'o', 's', 'e']```dopo il tuo codice deve stampare```python['e', 's', 'o', 'i', 'z', 'e', 'r', 'p', 'e', 's', 'o', 'c']```<jupyter_code>la = ['c', 'o', 's', 'e']
lb = ['p', 'r', 'e', 'z', 'i', 'o', 's', 'e']

# scrivi qui
lc = la + lb  # il + crea una NUOVA lista
lc.reverse()
print(lc)<jupyter_output>['e', 's', 'o', 'i', 'z', 'e', 'r', 'p', 'e', 's', 'o', 'c']<jupyter_text>Esercizio - potenzeIl codice seguente usa degli `insert` che come già detto non sono molto efficienti. Cerca di capire cosa fa, e riscrivilo usando solo `append` e `reverse`* il tuo codice deve funzionare per qualsiasi valore di `x`<jupyter_code>x = 2
la = [x]
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
print(la)
x = 2
la = [x]

# scrivi qui
la.append(la[-1]*2)
la.append(la[-1]*2)
la.append(la[-1]*2)
la.append(la[-1]*2)
la.reverse()
#print(la)<jupyter_output><empty_output><jupyter_text>Metodo sort Se una lista contiene elementi omogenei, è possibile ordinarla rapidamente con il metodo `sort`, che MODIFICA la lista su cui viene chiamato:<jupyter_code>la = [8,6,7,9]
la.sort()  # NOTA: sort non ritorna nulla !!!
la<jupyter_output><empty_output><jupyter_text>Anche le stringhe sono ordinabili:<jupyter_code>lb = ['Boccaccio', 'Alighieri', 'Manzoni', 'Leopardi']
lb.sort()
lb<jupyter_output><empty_output><jupyter_text>Una lista con elementi non comparabili tra loro non è ordinabile, e Python si lamenterà:<jupyter_code>lc = [3,4,'cavoli',7,'patate']<jupyter_output><empty_output><jupyter_text>```python>>> lc.sort()---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in ----> 1 lc.sort()TypeError: '<' not supported between instances of 'str' and 'int'```  Esercizio - numlistData la lista `la = [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]` 1. trova il min, max e valore mediano (SUGGERIMENTO: ordinala ed estrai i giusti valori)2. crea una lista solo con gli elementi a indici pari (per es [10, 72, 11, ..], nota che ".." indica che lista non è completa !) e ricalcola i valori di min, max e mediana3. rifai lo stesso con gli elementi ad indici dispari (per es [60, 118,..])Dovresti ottenere:```bashla: [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]pari: [10, 72, 11, 56, 120]dispari: [60, 118, 71, 89, 175]ordinati:   [10, 11, 56, 60, 71, 72, 89, 118, 120, 175]ordinati pari:   [10, 11, 56, 72, 120]ordinati dispari:   [60, 71, 89, 118, 175]la: Min:  10  Max. 175  Median:  72pari: Min:  10  Max. 120  Median:  56dispari: Min:  60  Max. 175  Median:  89```<jupyter_code>#jupman-purge-output

la = [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]

# scrivi qui

pari = la[0::2]    # prendiamo solo elementi ad indici pari
dispari = la[1::2] # prendiamo solo elementi ad indici dispari

print("originale:" , la)
print("pari:", pari)
print("dispari:", dispari)

la.sort()
pari.sort()
dispari.sort()

print()
print("ordinata:  " , la)
print("ordinata pari:  " , pari)
print("ordinata dispari:  " , dispari)
print()
print("originale: Min: ", la[0], " Max." , la[-1], " Median: ", la[len(la) // 2])
print("pari: Min: ", pari[0], " Max." , pari[-1], " Median: ", pari[len(pari) // 2])
print("dispari: Min: ", dispari[0], " Max." , dispari[-1], " Median: ", dispari[len(dispari) // 2])<jupyter_output>originale: [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]
pari: [10, 72, 11, 56, 120]
dispari: [60, 118, 71, 89, 175]

ordinata:   [10, 11, 56, 60, 71, 72, 89, 118, 120, 175]
ordinata pari:   [10, 11, 56, 72, 120]
ordinata dispari:   [60, 71, 89, 118, 175]

originale: Min:  10  Max. 175  Median:  72
pari: Min:  10  Max. 120  Median:  56
dispari: Min:  60  Max. 175  Median:  89<jupyter_text>Metodo join - da liste a stringheData una stringa che funge da separatore, e una sequenza come per esempio una lista `la` contenente solo stringhe, è possibile  concatenarle in una sola stringa (nuova) con il metodo `join`:<jupyter_code>la = ['Quando', 'fuori', 'piove']

'SEPARATORE'.join(la)<jupyter_output><empty_output><jupyter_text>Come separatore possiamo mettere qualunque carattere, come uno spazio:<jupyter_code>' '.join(la)<jupyter_output><empty_output><jupyter_text>Nota che la lista originale non viene modificata:<jupyter_code>la<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Questo codice cosa produce?```python''.join(['a','b','c']).upper()```1. un errore (quale?)2. una stringa (quale?)3. una lista (quale?) **RISPOSTA**: La 2: produce la stringa `'ABC'`: prima prende tutti i caratteri dalla lista `['a','b','c']` e li unisce separandoli con lo spazio vuoto `''` formando `'abc'`, poi questa stringa viene resa tutta maiuscola con `upper()`. **DOMANDA**: Questa codice cosa produce?```python'A'.join('porto')```1. una stringa (quale?)2. un errore (quale?)3. una lista (quale?) **RISPOSTA**: la 1: produce la stringa `'pAoArAtAo'` - abbiamo detto che `join` prende come input una sequenza, quindi non siamo vincolati a passargli liste ma possiamo anche passare direttamente una stringa, che è una sequenza di caratteri. `join` intervallerà quindi ogni carattere della stringa con il separatore che forniamo prima del punto. **DOMANDA**: Questo codice cosa produce?```python'\''.join('mmmm')```1. un errore (quale?)2. una stringa (quale?) **RISPOSTA**: La 2: `\'` è una sequenza di escape che rappresenta il carattere singolo apice `'`, quindi otterremo `m'm'm'm` **DOMANDA**: Data una stringa qualsiasi `s` e una lista di stringhe qualsiasi `la` di almeno due elementi, il seguente codice darà sempre lo stesso risultato - quale ? (pensaci, e se non sai rispondere prova a mettere dei valori a caso di `s` e `la`)```pythonlen(s) <= len(s.join(la))```1. un errore (quale?)2. una stringa (quale?)3. altro (cosa?) **RISPOSTA**: La 3: il codice produrrà sempre il booleano `True` perchè `s.join(la)` produce una stringa contenente tutte le stringhe in `la` intervallate dalla stringa `s`. Quindi la lunghezza di questa stringa sarà sempre uguale o superiore alla lunghezza di `s`: comparando le due lunghezze con l'operatore `<=` otterremo sempre il booleano `True`.Esempio```pythons = "ab"la = ['uief','cb','sd']len(s) <= len(s.join(la))```  Esercizio - barzoletta Data la stringa:```pythonsa = 'barzoletta'```scrivi del codice che crea una NUOVA stringa `sb` cambiando la stringa originale in modo che risulti:```python>>> print(sb)'barzelletta'```* **USA** il metodo `insert` e riassegnazione di celle* **NOTA**: non puoi usarle su una stringa, perchè è IMMUTABILE - dovrai quindi prima convertire la stringa in una lista<jupyter_code>#jupman-purge-output

sa = 'barzoletta'

# scrivi qui

la = list(sa)
la[4] = 'e'
la.insert(5,'l')
sb = ''.join(la)
print(sb)<jupyter_output>barzelletta<jupyter_text>Esercizio - dub dab dib dobScrivi del codice che data una lista di stringhe `la`, associa alla variabile `s` una stringa con le stringhe concatenate separate da virgole e uno spazioEsempio: Data`la = ['dub', 'dab','dib', 'dob']`dopo il tuo codice, dovresti ottenere questi risultati:```python>>> print(s)dub, dab, dib, dob>>> len(s)18```<jupyter_code>la = ['dub', 'dab','dib', 'dob']

# scrivi qui

s = ', '.join(la)

#print(s)
#len(s)<jupyter_output><empty_output><jupyter_text>Esercizio - ghirigoriData una lista di stringhe `la` e una lista di tre separatori `seps`, scrivi del codice che stampa gli elementi di `la` separati dal primo separatore, seguiti dal secondo separatore, seguiti dagli elementi di `la` separati dal terzo separatore.* il tuo codice deve funzionare con qualunque lista `la` e `seps` Esempio: dati```pythonla = ['ghi','ri','go','ri']seps = [',','_','+']```Dopo il tuo codice, deve stampare:```ghi,ri,go,ri_ghi+ri+go+ri```<jupyter_code>la = ['ghi','ri','go','ri']
seps = [',','_','+']

# scrivi qui

#print(seps[0].join(la) + seps[1] + seps[2].join(la))<jupyter_output><empty_output><jupyter_text>Esercizio - welldone Data la lista```pythonla = ["walnut", "eggplant", "lemon", "lime", "date", "onion", "nectarine", "endive" ]: ```1. Crea un'altra lista (chiamala `nuova`) contenente il primo carattere di ogni elemento di `la`2. Aggiungi uno spazio a `nuova` all aposizione 4 e attacca un punto esclamativo (`'!'`) alla fine3. Stampa la lista4. Stampa il contenuto della lista unendo tutti gli elementi con uno spazio vuoto (per es usa il metodo `join`: `"".join(nuova)`)Dovresti ottenere:```['w', 'e', 'l', 'l', ' ', 'd', 'o', 'n', 'e', '!'] well done!```<jupyter_code>la = ["walnut", "eggplant", "lemon", "lime", "date", "onion", "nectarine", "endive" ]

# scrivi qui

nuova = []
nuova.append(la[0][0])
nuova.append(la[1][0])
nuova.append(la[2][0])
nuova.append(la[3][0])
nuova.append(la[4][0])
nuova.append(la[5][0])
nuova.append(la[6][0])
nuova.append(la[7][0])

nuova.insert(4," ")
nuova.append("!")

print(nuova)
print("\n", "".join(nuova))<jupyter_output>['w', 'e', 'l', 'l', ' ', 'd', 'o', 'n', 'e', '!']

 well done!<jupyter_text>Metodo split - da stringhe a listeIl metodo `split` delle stringhe fa l'opposto di `join`: viene chiamato su una stringa e come parametro viene passato un separatore, che può essere un singolo carattere o una sottostringa. Il risultato è una lista di stringhe senza il separatore.<jupyter_code>"E' giunto il momento di dividere il tesoro".split("il")<jupyter_output><empty_output><jupyter_text>Chiamando `split` senza argomenti come separatori vengono usati in genere i _blank_ (spazio, a capo `\n`, tab `\t` , etc)<jupyter_code>s = "E' giunto il\nmomento di    dividere\til tesoro"
print(s)
s.split()<jupyter_output><empty_output><jupyter_text>E' anche possibile limitare il numero di elementi da dividere specificando l'argomento `maxsplit`:<jupyter_code>s.split(maxsplit=2)<jupyter_output><empty_output><jupyter_text>**ATTENZIONE**: Che succede se la lista _non_ contiene il separatore? Ricordati di considerare anche questo caso!<jupyter_code>"Parlo e straparlo senza mai fare una pausa".split(',')<jupyter_output><empty_output><jupyter_text>**DOMANDA**: Guarda questo codice. Stamperà qualcosa alla fine? O produrrà un errore? 1.  ```python    "porta\tgirevole".split()    ```1.  ```python    "porre particolare\t\nattenzione".split()    ```1.  ```python    "non ti\tscordar\ndi\tme".split('\t')    ```    1.  ```python    "non ti scordar\ndi\tme".split(' ')    ```1.  ```python    "Il Guardiano dell'Abisso ci osservava minaccioso".split('abisso')[1]    ```    1.  ```python    "".split('abisso')[0]    ```    1.  ```python    "abisso_OOOO_abisso".split('abisso')[0]    ```  Esercizio - trash danceTi hanno ingaggiato per ballare nell'ultimo video della nota band _Spazzatura Melodica_. Non puoi perdere questa occasione e ti lanci a leggere la partitura, ma la trovi piena di errori (gli Spazzatura non hanno certo bisogno di saper scrivere spartiti per andare in tv). Ci sono strani simboli e l'ultima battuta è troppo lunga (dopo la sesta battuta) e va messa una riga alla volta. Scrivi del codice che sistema la partitura in una lista `dance`Esempio - data:```pythonmusica = "Zam Dam\tZa Bum Bum\tZam\tBam To Tum\tRa Ta Pam\tBar Ra\tRammaGumma  Unza\n\t\nTACAUACA \n BOOMBOOM!"```dopo il tuo codice deve risultare:```python>>> print(dance)['Zam Dam', 'Za Bum Bum', 'Zam', 'Bam To Tum', 'Ra Ta Pam', 'Bar Ra', 'RammaGumma', 'Unza', 'TACAUACA', 'BOOMBOOM!']```<jupyter_code>#jupman-purge-output

musica = "Zam Dam\tZa Bum Bum\tZam\tBam To Tum\tRa Ta Pam\tBar Ra\tRammaGumma  Unza\n\t\nTACAUACA \n BOOMBOOM!"

# scrivi qui

dance = musica.split('\t',maxsplit=6)
dance = dance[:-1] + dance[-1].split()
dance<jupyter_output><empty_output><jupyter_text>Esercizio  - spazzatura In tourGli _Spazzatura Melodica_ tornano a colpire nel nuovo tour dove presentano le hit dell'estate. La casa discografica fornisce però le vendite con numeri in formato anglosassone, e per comunicarle ai media italiani è necessaria prima una conversione. Scrivi del codice che date le `hits` e una `posizione` nella classifica (da `1` a `4`) mostra il numero di copie vendute- **NOTA**: le virgole devono essere sostituite con puntiEsempio - dati:```pythonhits = """6,230,650 - Ti amo come i pomodori ammuffiti nel frigorifero2,000,123 - Il dolore di vivere pieni di soldi100,000 - Le groupies non sono mai abbastanza837 - Ti ricordi i cassonetti l'estate..."""posizione = 1    i pomodoriposizione = 4   i cassonetti```Dopo il tuo codice, deve risultare:```La numero 1 in classifica "Ti amo come i pomodori ammuffiti nel frigorifero" ha venduto 6.230.650 copie```<jupyter_code>#jupman-purge-output
hits = """6,230,650 - Ti amo come i pomodori ammuffiti nel frigorifero
2,000,123 - Il dolore di vivere pieni di soldi
100,000 - Le groupies non sono mai abbastanza
837 - Ti ricordi i cassonetti l'estate..."""

posizione = 1   # i pomodori
#posizione = 4  # i cassonetti

# scrivi qui

lst = hits.split('\n')
ext = lst[posizione-1].split(' - ')

print("La numero", posizione, "in classifica", '"' + ext[1] + '"', 
      'ha venduto', '.'.join(ext[0].split(',')), 'copie')<jupyter_output>La numero 1 in classifica "Ti amo come i pomodori ammuffiti nel frigorifero" ha venduto 6.230.650 copie<jupyter_text>Esercizio - moltelinee        Dato la seguente stringa di testo:```python"""Questa è una stringadi testo sudiverse linee che non dice niente. """```1. stampala2. stampa quante linee, parole e caratteri contiene3. metti in ordine alfabetico le parole e stampale le prime e ultime in ordine lessicograficoDovresti ottenere:```Questa è una stringadi testo sudiverse linee che non dice niente.Linee: 3 parole: 13 charatteri: 67['Q', 'u', 'e', 's', 't', 'a', ' ', 'è', ' ', 'u', 'n', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', 'a', '\n', 'd', 'i', ' ', 't', 'e', 's', 't', 'o', ' ', 's', 'u', '\n', 'd', 'i', 'v', 'e', 'r', 's', 'e', ' ', 'l', 'i', 'n', 'e', 'e', ' ', 'c', 'h', 'e', ' ', 'n', 'o', 'n', ' ', 'd', 'i', 'c', 'e', ' ', 'n', 'i', 'e', 'n', 't', 'e', '.']67Prima parola:  QuestaUltima parola: è['Questa', 'che', 'di', 'dice', 'diverse', 'linee', 'niente.', 'non', 'stringa', 'su', 'testo', 'una', 'è']```<jupyter_code>#jupman-purge-output

s = """Questa è una stringa
di testo su
diverse linee che non dice niente."""


# scrivi qui

# 1) stampa
print(s)
print("")

# 2) stampa le linee, parole e caratteri
lines = s.split('\n')

# NOTA: le parole sono separate da uno spazio o da un ritorno a capo (newline)

words = lines[0].split(' ') + lines[1].split(' ') + lines[2].split(' ')
num_chars = len(s)
print("Linee:", len(lines), "parole:", len(words), "caratteri:", num_chars)

# modo alternativo per numero di caratteri
print("")
characters = list(s)
num_chars2 = len(characters)
print(characters)
print(num_chars2)

# 3. ordina alfabeticamente le parole e stampa la prima e ultima in ordine lessicografico

words.sort() # NOTA: non ritorna NIENTE !!!!
print("")
print("Prima parola: ", words[0])
print("Ultima parola:", words[-1])
print(words)<jupyter_output>Questa è una stringa
di testo su
diverse linee che non dice niente.

Linee: 3 parole: 13 caratteri: 67

['Q', 'u', 'e', 's', 't', 'a', ' ', 'è', ' ', 'u', 'n', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', 'a', '\n', 'd', 'i', ' ', 't', 'e', 's', 't', 'o', ' ', 's', 'u', '\n', 'd', 'i', 'v', 'e', 'r', 's', 'e', ' ', 'l', 'i', 'n', 'e', 'e', ' ', 'c', 'h', 'e', ' ', 'n', 'o', 'n', ' ', 'd', 'i', 'c', 'e', ' ', 'n', 'i', 'e', 'n', 't', 'e', '.']
67

Prima parola:  Questa
Ultima parola: è
['Questa', 'che', 'di', 'dice', 'diverse', 'linee', 'niente.', 'non', 'stringa', 'su', 'testo', 'una', 'è']<jupyter_text>Metodo countSi può ottenere il numero di occorrenze di un certo elemento in una lista usando il metodo `count`.<jupyter_code>la = ['c', 'o', 'r', 'r', 'o', 'b', 'o', 'r', 'a', 'r', 'e']
la.count('c')
la.count('o')
la.count('r')<jupyter_output><empty_output><jupyter_text>Non abusare count    **ATTENZIONE**: `count` **viene spesso usato in modo errato / inefficiente**Chiediti sempre:    1. la lista potrebbe contenere duplicati? Ricordati che verranno tutti conteggiati!2. la lista potrebbe _non_ contenere l'oggetto da contare? Ricordati di gestire anche questo caso!3. `count` compie una ricerca in tutta la lista, che può essere inefficiente: è proprio necessaria, o sappiamo già l'intervallo in cui cercare? **DOMANDA**: Guarda i frammenti di codice seguenti, e per ciascuno cerca di indovinare che risultato produce (o se risulta in un errore).1.  ```python    ['A','aa','a','aaAah',"a", "aaaa"[1], " a "].count("a")    ```    1.  ```python    ["il", "castigo", "degli", "stolti"].count('Stolti') == 1    ```1.  ```python    lista = ['oasi','dattero','oasi','cocco','dattero','cocco']    print(lista.count('dattero') == 1)    ```1.  ```python    lista = ['oasi','dattero','oasi','cocco','dattero','cocco']    print(lista[4] == 'dattero')    ```1.  ```python    ['2',2,"2",2,float("2"),2.0, 4/2,"1+1",int('3')-float('1')].count(2)    ```    1.  ```python    [].count([])    ```1.  ```python    [[],[],[]].count([])    ```      Esercizio - vita di campagnaData una lista `campagna`, scrivi del codice che stampa `True` se la prima metà contiene un numero di elementi `el1` uguale al numero di elementi `el2` nella seconda metà.<jupyter_code>#jupman-purge-output
el1,el2 = 'badili', 'zappe'    # True
#el1,el2 = 'badili', 'badili'  # False
#el1,el2 = 'cariole', 'aratri' # True
#el1,el2 = 'badili', 'cariole' # False

campagna = ['aratri','cariole', 'badili',  'cariole', 'badili','zappe', 'cariole',
            'zappe', 'aratri',  'cariole', 'aratri',  'badili','aratri','zappe']

# scrivi qui
mid = len(la)//2
la[:mid].count(el1) == la[mid:].count(el2)<jupyter_output><empty_output><jupyter_text>Metodo indexIl metodo `index` ci permette di trovare l'indice della PRIMA occorrenza di un elemento.<jupyter_code>#      0   1   2   3   4
la = ['p','a','e','s','e']
la.index('p')
la.index('a')  
la.index('e')  # troviamo la PRIMA occorrenza<jupyter_output><empty_output><jupyter_text>Se l'elemento che cerchiamo non è presente, otterremo un errore: ```python>>> la.index('z')---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in ----> 1 la.index('z')ValueError: 'z' is not in list``` Opzionalmente, puoi specificare un indice da dove iniziare a cercare (**incluso**):<jupyter_code># 0   1   2   3   4   5   6   7   8   9   10
['a','c','c','a','p','a','r','r','a','r','e'].index('a',6)<jupyter_output><empty_output><jupyter_text>E anche dove finire (**escluso**): ```python 0   1   2   3   4   5   6   7   8   9   10['a','c','c','a','p','a','r','r','a','r','e'].index('a',6,8)---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in       1  0   1   2   3   4   5   6   7   8   9   10----> 2 ['a','c','c','a','p','a','r','r','a','r','e'].index('a',6,8)ValueError: 'a' is not in list```  Non abusare index     **ATTENZIONE**: `index` **viene spesso usato in modo errato / inefficiente**Chiediti sempre:    1. la lista su cui operare potrebbe contenere duplicati? Ricordati che solo il _primo_ verrà trovato!2. la lista potrebbe _non_ contenere l'elemento cercato? Ricordati che in questo caso il programma lancerà un errore!    3. `index` compie una ricerca in tutta la lista, che può essere inefficiente: è proprio necessaria, o sappiamo già l'intervallo in cui cercare? 4. se vogliamo sapere se un `elemento` è in una posizione nota a priori (es `3`), `index` non ci serve, basta scrivere `lista[3] == elemento`. Usando `index` potrebbe trovare caratteri duplicati che stanno _prima_ o _dopo_ di quello che vogliamo verificare! **DOMANDA**: Guarda i frammenti di codice seguenti, e per ciascuno cerca di indovinare che risultato produce (o se risulta in un errore). 1.  ```python    ['arco','barca','conca','duna'].index('conca') == ['arco','barca','conca','duna'].index('conca',1)    ```1.  ```python    ['azzurro','blu','celeste','puffo'][-1:].index('celeste')    ```    1.  ```python    strada = ['asfalto','bitume','cemento','ghiaia']    print('malta' in strada or strada.index('malta'))    ```    1.  ```python    strada = ['asfalto','bitume','cemento','ghiaia']    print('malta' in strada and strada.index('malta'))    ```1.  ```python    strada = ['asfalto','bitume','malta','ghiaia']    print('malta' in strada and strada.index('malta'))    ```1.  ```python    la = [0,5,10]    la.reverse()    print(la.index(5) > la.index(10))    ```  Esercizio - SpatočIn passato hai avuto conosciuto il pittore slavo Spatoč quando era ancora povero in canna. Ti ha regalato 2 o 3 quadri (non ricordi) dal dubbio valore artistico che hai nascosto in soffitta, ma dalla TV apprendi che Spatoč è diventato un artista di fama internazionale. Corri quindi in soffitta a recuperare i quadri, persi tra le mille cianfrusaglie. Ogni quadro è contenuto in uno `[ ]` scatolone, ma non sai in quale scaffale. Scrivi del codice che stampa dove sono.- gli scaffali sono **numerati da 1**. Se il terzo quadro non è trovato, stampa `0`.- **NON** usare cicli nè `if`- **SUGGERIMENTO:** stampare i primi due (che ci sono sempre) è facile, mentre per l'ultimo riguardati [Booleani - ordine di valutazione](https://it.softpython.org/basics/basics2-bools-sol.htmlOrdine-di-valutazione)Esempio 1 - data:<jupyter_code>#  1  2     3            4      5          
soffitta = [3,"\\", ["quadro"], "---", ['quadro'], 
         #  6      7          8             9           10
            5.23, ['viti'], ['pattini'], ["quadro"], ['lampada']]<jupyter_output><empty_output><jupyter_text>il tuo codice deve stampare:```scaffale primo quadro:  3scaffale secondo quadro: 5scaffale terzo quadro: 9```Esempio 2 - data:<jupyter_code># 1          2     3            4            5           6          7
soffitta = [["quadro"],  "--", ['pattini'], ['quadro'], ["statua"], ['viti'], ['stivali']]<jupyter_output><empty_output><jupyter_text>il tuo codice deve stampare:```scaffale primo quadro: 1scaffale secondo quadro: 4scaffale terzo quadro: 0```<jupyter_code>#jupman-purge-output
        #   1  2     3            4      5          6      7          8             9           10
soffitta = [3,"\\", ["quadro"], "---", ['quadro'], 5.23, ['viti'], ['pattini'], ["quadro"], ['lampada']]
#  3,5,9
            #   1          2     3            4            5           6          7
#soffitta = [["quadro"],  "--", ['pattini'], ['quadro'], ["statua"], ['viti'], ['stivali']]
#  1,4,0


# scrivi qui

i1 = soffitta.index(['quadro'])
print("scaffale primo quadro:", i1+1)
i2 = soffitta.index(['quadro'], i1+1)
print("scaffale secondo quadro:", i2+1)
i3 = int(['quadro'] in soffitta[i2+1:]) and (soffitta.index(['quadro'], i2+1) + 1)
print("scaffale terzo quadro:", i3)<jupyter_output>scaffale primo quadro: 3
scaffale secondo quadro: 5
scaffale terzo quadro: 9<jupyter_text>Metodo remove `remove` prende come parametro un oggetto, cerca la PRIMA cella che contiene quell'oggetto e la elimina:<jupyter_code>#     0 1 2 3 4 5
la = [6,7,9,5,9,8]   # il 9 è alla cella con indice 2 e 4
la.remove(9)   # cerca la prima cella contenente il numero 9
la<jupyter_output><empty_output><jupyter_text>Come si può vedere, la cella che era all'indice `2` e che conteneva la PRIMA occorrenza di `9` è stata eliminata. La cella contenente la SECONDA occorrenza di `9` invece è ancora lì. Se si cerca di rimuovere un oggetto non presente, si riceve un errore: ```pythonla.remove(666)---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in ----> 1 la.remove(666)ValueError: list.remove(x): x not in list```  Non abusare remove    **ATTENZIONE**: `remove` **viene spesso usato in modo errato / inefficiente**Chiediti sempre:    1. la lista potrebbe contenere duplicati? Ricordati che verrà rimosso solo il primo!2. la lista potrebbe _non_ contenere l'oggetto cercato? Ricordati di gestire anche questo caso!3. `remove` compie una ricerca in tutta la lista, che può essere inefficiente: è proprio necessaria, o sappiamo già la posizione `i` dove è presente l'elemento da rimuovere? In tal caso conviene usare `.pop(i)` **DOMANDA**: Guarda i frammenti di codice seguenti, e per ciascuno cerca di indovinare che risultato produce (o se risulta in un errore).1.  ```python    la = ['a','b','c','b']    la.remove('b')    print(la)    ```1.  ```python    la = ['a','b','c','b']    x = la.remove('b')    print(x)    print(la)    ```    1.  ```python    la = ['a','d','c','d']    la.remove('b')    print(la)    ```1.  ```python    la = ['a','bb','c','bbb']    la.remove('b')    print(la)    ```        1.  ```python    la = ['a','b','c','b']    la.remove('B')        print(la)    ```    1.  ```python    la = ['a',9,'99',9,'c',str(9),'999']    la.remove("9")        print(la)    ```1.  ```python    la = ['nun', 'me', 'fregà']    la.remove('nun').remove('me').remove('fregà')    print(la)    ```1.  ```python    la = ['nun', 'me', 'fregà']    la.remove('nun')    la.remove('me')    la.remove('fregà')    print(la)    ```    1.  ```python    la = [4,5,7,10]    11 in la or la.remove(11)        print(la)    ```     1.  ```python    la = [4,5,7,10]    11 in la and la.remove(11)        print(la)    ``` 1.  ```python    la = [4,5,7,10]    5 in la and la.remove(5)    print(la)    ```    1.  ```python    la = [9, [9], [[9]], [[[9]]] ]    la.remove([9])    print(la)    ```        1.  ```python    la = [9, [9], [[9]], [[[9]]] ]    la.remove([[9]])    print(la)    ```          Esercizio - nobScrivi del codice che rimuove dalla lista `la` tutti i numeri contenuti nella lista di 3 elementi `lb`* il tuo codice deve funzionare con qualsiasi lista `la` e `lb` di 3 elementi* puoi assumere che `la` contenga esattamente DUE occorrenze di tutti gli elementi di `lb` (più eventuali altri numeri)Esempio - dati:```pythonlb = [8,7,4]la = [7,8,11,8,7,4,5,4]```dopo il tuo codice deve risultare```python>>> print(la)[11, 5]```<jupyter_code>lb = [8,7,4]
la = [7,8,11,8,7,4,5,4]

# scrivi qui

la.remove(lb[0])
la.remove(lb[0])
la.remove(lb[1])
la.remove(lb[1])
la.remove(lb[2])
la.remove(lb[2])
#print(la)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.164748147312192, 'fraction_numerical': 0.02546740397998721, 'mean_word_length': 4.65546218487395, 'pattern_counts': {'":': 0, '<': 251, '<?xml version=': 0, '>': 315, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 43, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '65', 'dir': 'jupyter-structured-clean-dedup', 'id': '132776', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 21122, 'n_tokens_neox': 20462, 'n_words': 6166, 'path': 'lists/lists3-sol.ipynb', 'repo_name': 'DavidLeoni/softpython-', 'size': '53166'}