# --- # jupyter: # jupytext: # formats: ipynb,py:percent # text_representation: # extension: .py # format_name: percent # format_version: '1.3' # jupytext_version: 1.14.0 # kernelspec: # display_name: Python 3 (ipykernel) # language: python # name: python3 # --- # %% [markdown] toc=true slideshow={"slide_type": "notes"} #

Table of Contents

#
# %% [markdown] slideshow={"slide_type": "slide"} # # # Fondamenti di Programmazione # # # **Andrea Sterbini** # # lezione 6 - 20 ottobre 2022 # %% [markdown] slideshow={"slide_type": "subslide"} # # Wooclap: quanto ho capito finora ? # ![](wooclap6.png) # %% [markdown] slideshow={"slide_type": "subslide"} # # Ordinamento di un contenitore # # Abbiamo visto che il metodo **sort** delle liste ci permette di ordinarle in ordine crescente. # # Come fare per ordinarle in modo più sofisticato? # # Esempio: # **`[ 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette']`** : # - per **lunghezza crescente delle parole** # - e se sono di lunghezza uguale, **in ordine alfabetico** # # # # # # %% [markdown] slideshow={"slide_type": "fragment"} # Potrei **trasformare ciascun elemento in una coppia**: # - lunghezza della parola # - parola # # e cercare di ordinare la nuova lista di coppie # %% slideshow={"slide_type": "fragment"} L = [ 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette'] # costruisco la lista di coppie L1 = [] for elemento in L: L1.append((len(elemento), elemento)) L1 # la ordino L1.sort() L1 # %% [markdown] slideshow={"slide_type": "subslide"} # ### FUNZIONA! MA PERCHE'? # Perchè quando dobbiamo ordinare una lista di soppie
per confrontare due coppie: # - prima confrontiamo il primo (lunghezza della parole) # - poi solo in caso di parità passiamo a confrontare il secondo # (ordine alfabetico delle parole) # # ... e questo era proprio quello che volevamo! # %% slideshow={"slide_type": "fragment"} # a questo punto basta estrarre dalle coppie solo la parola originale L2 = [] for lunghezza,elemento in L1: L2.append(elemento) L2 # %% [markdown] slideshow={"slide_type": "subslide"} # ## Ma se volessi che l'ordinamento fosse **STABILE** ? # Ovvero che elementi "uguali" che erano in un certo ordine relativo # # mantengano lo stesso ordine relativo # # **BASTA aggiungere alla tupla anche la posizione originale** # %% slideshow={"slide_type": "fragment"} ## Ma se volessi che l'ordinamento fosse **STABILE** ? L = [ 'uno', 'due', 'tre', 'sette', 'cinque', 'sei', 'sette'] # costruisco la lista di coppie L1 = [] # assieme all'elemento ne estraggo la posizione for i,elemento in enumerate(L): # aggiungo la posizione *i* come ulteriore criterio L1.append((len(elemento), elemento, i)) L1 # la ordino L1.sort() L1 # %% [markdown] slideshow={"slide_type": "subslide"} # ### Questo tipo di trasformazione di ciascun elemento si chiama trasformazione di Schwartz # # e può essere semplificata introducendo una piccola funzione che trasforma ciascun elemento # # da passare a **sorted** (che tra l'altro è stabile) # %% slideshow={"slide_type": "fragment"} # trasformazione di un solo elemento nella coppia corrispondente def trasforma_elemento(parola): return len(parola), parola # con la funzione *sorted* costruiamo una nuova lista ordinata # fornendo col parametro *key* la funzione di trasformazione sorted(L, key=trasforma_elemento) # %% [markdown] slideshow={"slide_type": "fragment"} # **MA INVECE** che definire una nuova funzione apposta # # (che magari ci serve solo in questa occasione) # # sarebbe comodo avere un modo per creare funzioni **USA e GETTA** # # %% [markdown] slideshow={"slide_type": "subslide"} # ## Funzioni anonime (espressioni *lambda*) # # Notate che la funzione precedente è estremamente semplice ed ha un solo compito: # - riceve dei parametri # - ritorna SOLO una espressione **SENZA ESEGUIRE ALTRE ISTRUZIONI** # # E può essere abbreviata senza usare la keyword **return** in # ```python # lambda argomenti: espressione # ``` # %% slideshow={"slide_type": "subslide"} # quindi la funzione *trasforma_elemento* # può essere scritta direttamente come # trasforma_elemento = lambda elemento: (len(elemento), elemento) trasforma_elemento('Paperino') # sorted(L, key=lambda elemento: (len(elemento), elemento)) # %% [markdown] slideshow={"slide_type": "subslide"} # ### RIASSUNTO # # Per ordinare un contenitore di elementi secondo criteri complessi: # - si definisce una funzione di trasformazione (o una lambda) che: # - riceve l'elemento da trasformare # - torna una tupla contenente nell'ordine i dati # che servono a rappresentare i criteri complessi # %% [markdown] slideshow={"slide_type": "subslide"} # **Esempio:** ordiniamo la lista di parole # - in ordine CRESCENTE di lunghezza # - e in caso di parità in ordine alfabetico DECRESCENTE (Z->A) # # qui abbiamo un problema in più, **i due ordinamenti sono opposti!** # # Uno dei due va rovesciato, # # perchè i confronti tra sequenze sono sempre monodirezionali # # cioè tutti gli ordinamenti vanno nella stessa direzione # %% slideshow={"slide_type": "fragment"} # definiamo la funzione di trasformazione adatta # NON possiamo rovesciare l'ordinamento alfabetico! # ALLORA rovesciamo l'ordinamento delle lunghezze def trasforma_elemento(el): return -len(el), el # lunghezza negativa # vediamo cosa succede sorted(L, key=trasforma_elemento) # E' tutto a rovescio! sorted(L, key=trasforma_elemento, reverse=True) # ora va bene # %% slideshow={"slide_type": "fragment"} # A questo punto possiamo riscrivere la trasformazione # usando una funzione anonima con lambda # (notate le parentesi per creare la tupla) sorted(L, key=lambda el: (-len(el),el), reverse=True) # %% [markdown] slideshow={"slide_type": "subslide"} # # Wooclap: Secondo voi cosa ottengo da questo sorted? # ![](wooclap6.png) # %% # Soluzione # Supponiamo di sapere età # e genere di alcuni personaggi L = [ (27, 'M', 'Paperino'), (31, 'M', 'Topolino'), (26, 'F', 'Paperina'), (32, 'F', 'Minnie')] def trasforma_elemento(terna): eta, genere, nome = terna return len(nome), genere, eta sorted(L, key=trasforma_elemento) # %% [markdown] slideshow={"slide_type": "slide"} # # List comprehension # ## una sintassi semplificata per costruire contenitori # # Spessissimo dobbiamo raccogliere in un contenitore più elementi e scriviamo roba del tipo di # %% slideshow={"slide_type": "fragment"} # dati dei valori lista_di_interi = [12, 34, 61, 2, 4, 7] # voglio costruire la lista dei cubi lista_di_cubi = [] for x in lista_di_interi: lista_di_cubi.append(x**3) lista_di_cubi # %% [markdown] slideshow={"slide_type": "fragment"} # - iniziamo costruendo una lista vuota # - iteriamo su un contenitore di elementi # - trasformiamo ciascun elemento # - lo aggiungiamo alla lista # - torniamo la lista ottenuta # # Sarebbe bello poter usare una sintassi più leggibile # # (che non ci obbliga a **simulare** il codice nella testa) # %% slideshow={"slide_type": "subslide"} lista_di_interi = [12, 34, 2, 61, 2, 4, 7] # Con la sintassi della list-comprehension [ X**3 for X in lista_di_interi ] # - le parentesi indicano che contenitore stiamo costruendo (lista) # - il *for* indica su quale sequenza stiamo iterando # - l'espressione all'inizio (X**3) come produciamo ogni nuovo valore # %% slideshow={"slide_type": "fragment"} # possiamo costruire altri tipi di contenitore # INSIEMI { X**3 for X in lista_di_interi } # %% slideshow={"slide_type": "fragment"} # DIZIONARI che contengono coppie chiave:valore { X : X**3 for X in lista_di_interi } # %% slideshow={"slide_type": "fragment"} # TUPLE (qui ci vuole la parola tuple) tuple( X**3 for X in lista_di_interi ) # %% [markdown] slideshow={"slide_type": "subslide"} # ### e possiamo anche condizionare quali elementi trasformare # # ```python # [ espressione for variabile in contenitore # if condizione ] # ``` # %% slideshow={"slide_type": "fragment"} # Voglio i cubi SOLO dei numeri dispari { x : x**3 for x in lista_di_interi if x%2 } # %% [markdown] slideshow={"slide_type": "subslide"} # ### oppure costruire for nidificati # ```python # [ espressione for var1 in contenitore1 # for var2 in contenitore2 ] # ``` # %% slideshow={"slide_type": "fragment"} # costruisco l'insieme dei prodotti della tabellina del 10 # %pprint { X*Y for X in range(1,11) for Y in range(1,11) } # %% [markdown] slideshow={"slide_type": "subslide"} # ### oppure costruire contenitori nidificati # ```python # [ [ espressione for var1 in contenitore1 ] # for var2 in contenitore2 ] # ``` # %% slideshow={"slide_type": "fragment"} # Ad esempio la tabellina del 10 come lista di liste # (una lista per ogni riga) # %pprint [ [ X*Y for X in range(1,11) ] # per ogni Y costruisco la riga for Y in range(1,11) ] # %% [markdown] slideshow={"slide_type": "subslide"} # # Wooclap: Secondo voi cosa ottengo da questa list comprehension? # ![](wooclap6.png) # %% slideshow={"slide_type": "subslide"} ## Vediamo la soluzione alfabeto = "abcdefghijk" parola = "bigia" [ ''.join( c for c in alfabeto[alfabeto.index(X):] ) for X in parola] # %% [markdown] slideshow={"slide_type": "slide"} # # INTERVALLO (RAI - anni 70) # %% slideshow={"slide_type": "fragment"} language="html" #