Insiemi

Scarica zip esercizi

Naviga file online

Un insieme è una collezione mutabile senza ordine di elementi immutabili e distinti (cioè senza duplicati). Il tipo di dati in Python per rappresentare gli insiemi si chiama set.

Riferimenti:

Che fare

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 sets.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

Creare un insieme

Possiamo creare un insieme usando le parentesi graffe, e separando gli elementi da virgole ,

Proviamo un insieme di caratteri:

[2]:
s = {'b','a','d','c'}
[3]:
type(s)
[3]:
set

ATTENZIONE: GLI INSIEMI *NON* SONO ORDINATI !!!

NON CREDERE A QUELLO CHE VEDI !!

Proviamo a stampare l’insieme:

[4]:
print(s)
{'b', 'd', 'c', 'a'}

Come vedi, l’ordine in cui è stata effettuata la stampa è diverso da quello con cui abbiamo costruito l’insieme. A seconda della versione di Python che stai usando, sul tuo computer potrebbe essere diverso ancora!!

Questo perchè l’ordine negli insiemi NON è garantito: l’unica cosa che conta è se un elemento appartiene ad un insieme oppure no.

Come ulteriore dimostrazione, possiamo chiedere a Jupyter di mostrarci il contenuto dell’insieme, scrivendo solo la variabile s SENZA la print:

[5]:
s
[5]:
{'a', 'b', 'c', 'd'}

Adesso appare in ordine alfabetico ! Succede così perchè Jupyter quando mostra le variabili le stampa implicitamente non con la print ma con la pprint (pretty print), che SOLO per gli insiemi ci fa la cortesia di ordinare il risultato prima di stamparlo. Possiamo ringraziare, ma non lasciamo che ci confonda !!

Indice degli elementi: visto che gli insiemi non hanno ordine, chiedere a Python di estrarre un elemento ad una certa posizione non avrebbe senso. Quindi, diversamente da stringhe, liste e tuple, con gli insiemi NON è possibile ricavare un elemento a partire da un indice:

s[0]

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-352-c9c96910e542> in <module>
----> 1 s[0]

TypeError: 'set' object is not subscriptable

Abbiamo detto che un insieme ha solo elementi distinti, cioè senza duplicati - che succede se proviamo a metterli comunque ?

[6]:
s = {6,7,5,9,5,5,7}
[7]:
s
[7]:
{5, 6, 7, 9}

Notiamo che Python ha silenziosamente rimosso i duplicati.

Convertire sequenze in insiemi

Come per liste e stringhe, possiamo creare un set a partire da un’altra sequenza:

[8]:
set('acacia') # da stringa
[8]:
{'a', 'c', 'i'}
[9]:
set( [1,2,3,1,2,1,2,1,3,1] ) # da lista
[9]:
{1, 2, 3}
[10]:
set( (4,6,1,5,1,4,1,5,4,5) ) # da tupla
[10]:
{1, 4, 5, 6}

Di nuovo, notiamo come nell’insieme creato non siano presenti duplicati.

RICORDATI: Gli insiemi sono utili per rimuovere duplicati da una sequenza

Elementi mutabili e hash

Rivediamo la definizione di insieme data all’inizio:

Un insieme è una collezione mutabile senza ordine di elementi immutabili e distinti

Finora abbiamo creato l’insieme solo usando elementi immutabili come numeri e stringhe.

Cosa succede se mettiamo degli elementi mutabili, come liste?

>>> s = { [1,2,3], [4,5] }

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-a6c538692ccb> in <module>
----> 1 s = { [1,2,3], [4,5]  }

TypeError: unhashable type: 'list'

Otteniamo TypeError: unhashable type: 'list', che letteralmente significa che Python non è riuscito a calcolare lo spezzatino (hash) della lista. Cosa sarà mai questa particolare pietanza??

Cos’è lo hash? Lo hash di un oggetto è un numero che Python può associargli, per esempio puoi vedere lo hash di un oggetto con l’omonima funzione:

[11]:
hash( "Questa è una bella giornata" )  # stringa
[11]:
-1325950510056206031
[12]:
hash( 111112222223333333344444445555555555 )   # numero
[12]:
651300278308214397

Immagina che lo hash sia una specie di etichetta con queste caratteristiche:

  • è troppo breve per descrivere completamente l’oggetto a cui è associata (tradotto: data solo un’etichetta hash, non puoi ricostruire l’oggetto che rappresenta)

  • è abbastanza lunga per identificare quasi univocamente l’oggetto…

  • … anche se al mondo potrebbero esistere oggetti diversi hanno però associata esattamente la stessa etichetta

Cosa c’entra con i nostri insiemi? Lo hash ha vari utilizzi, ma tipicamente Python lo usa per ritrovare velocemente un’oggetto in collezioni basate sugli hash, come gli insiemi e i dizionari. Quanto velocemente? Parecchio: anche con insiemi enormi, otteniamo una risposta sempre in un tempo costante e brevissimo! In altre parole, la velocità di risposta non dipende dalla dimensione dell’insieme (salvo casi patologici).

Questa velocità è consentita dal fatto che dato un oggetto da cercare, Python è in grado di ricavare velocemente la sua etichetta hash: poi con l’etichetta in mano, riesce a individuare nel magazzino della memoria molto in fretta se vi sono oggetti che hanno la stessa etichetta. Se vengono trovati, saranno quasi sicuramente molto pochi, e basterà quindi confrontarli con quello cercato.

Gli oggetti *immutabili* hanno sempre lo stessa etichetta hash da quando sono creati fino alla fine del programma. Quelli mutabili invece no: ogni volta che li cambiamo, viene anche automaticamente cambiato l’hash. Immaginati un supermercato dove i commessi dispongono gli alimentari in base all’etichetta separando per esempio il caffè nello scaffale per la prima colazione e la varechina nello scaffale dei detersivi. Se sei un cliente e vuoi il caffè, guardi i cartelli e ti dirigi subito verso lo scaffale della prima colazione. Immagina cosa succederebbe se un mago malvagio potesse trasmutare gli oggetti già collocati negli scaffali in altri oggetti, quindi per esempio il caffè in varechina (assumiamo che al momento della trasmutazione oltre al caffè cambi anche l’etichetta hash). Sicuramente porterebbe tanta confusione, e se non si sta attenti, anche un gran mal di pancia.

Quindi per offrirti il vantaggio della ricerca rapida evitando situazioni disastrose, Python ti impone di collocare nell’insieme solo oggetti con hash stabile, cioè gli oggetti immutabili.

DOMANDA: Possiamo inserire una tupla dentro un insieme? Prova a verificare la tua supposizione con un esempio di codice.

Mostra risposta

Insieme vuoto

ATTENZIONE: Se scrivi {} otterrai un dizionario, NON un insieme !!!

Per creare un insieme vuoto dobbiamo chiamare la funzione set():

[13]:
s = set()
[14]:
s
[14]:
set()

ESERCIZIO: prova a scrivere nella cella qua sotto {} e guarda il tipo dell’oggetto ottenuto con type

Mostra soluzione
[15]:
# scrivi qui


DOMANDA: Possiamo inserire un insieme dentro un’altro insieme? Guarda bene la definizione di insieme, poi verifica le tuo supposizioni provando a scrivere del codice per creare un insieme che abbia dentro un’altro insieme.

ATTENZIONE: Per fare la verifica, NON usare la funzione set, usa solo creazione con parentesi graffe

Mostra risposta

DOMANDA: Se scriviamo una cosa del genere, cosa otterremo? (attento !)

set(set(['a','b']))
  1. un insieme con dentro 'a' e 'b'

  2. un insieme con dentro un insieme contenente gli elementi 'a' e 'b'

  3. un errore (quale?)

Mostra risposta

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {'oh','la','la'}
    
  2. set([3,4,2,3,2,2,2,-1])
    
  3. {(1,2),(2,3)}
    
  4. set('aba')
    
  5. str({'a'})
    
  6. {1;2;3}
    
  7. set(  1,2,3  )
    
  8. set( {1,2,3} )
    
  9. set( [1,2,3] )
    
  10. set( (1,2,3) )
    
  11. set(  "abc"  )
    
  12. set(  "1232"  )
    
  13. set( [ {1,2,3,2} ] )
    
  14. set( [ [1,2,3,2] ] )
    
  15. set( [ (1,2,3,2) ] )
    
  16. set( [ "abcb"   ] )
    
  17. set( [ "1232"   ] )
    
  18. set((1,2,3,2))
    
  19. set([(),()])
    
  20. set([])
    
  21. set(list(set()))
    

Esercizio: dedup

Scrivi del codice breve per creare una lista lb che contiene tutti gli elementi dalla lista la senza duplicati e ordinati alfabeticamente.

  • NON DEVE cambiare la lista originale la

  • NON usare cicli

  • il tuo codice dovrebbe funzionare con qualunque la

la = ['c','a','b','c','d','b','e']

dopo il tuo codice, dovresti ottenere:

>>> print(la)
['c', 'a', 'b', 'c', 'd', 'b', 'e']
>>> print(lb)
['a', 'b', 'c', 'd', 'e']
Mostra soluzione
[16]:
la = ['c','a','b','c','d','b','e']

# scrivi qui


la = ['c', 'a', 'b', 'c', 'd', 'b', 'e']
lb = ['a', 'b', 'c', 'd', 'e']

Frozenset

INFO: questo argomento è opzionale ai fini della comprensione del libro**

In Python esistono anche insiemi immutabili che si chiamano frozenset. Qui ci limitamo a ricordare che i frozenset essendo immutabili hanno un’etichetta hash associata e possono essere inseriti come elementi di altri insiemi. Per il resto rimandiamo alla documentazione ufficiale.

Operatori

Operatore

Risultato

Descrizione

len(set)

int

il numero di elementi nel set

el in set

bool

verifica se elemento è contenuto nel set

set | set

set

unione, crea un NUOVO set

set & set

set

intersezione, crea un NUOVO set

set - set

set

differenza, crea un NUOVO set

set ^ set

set

differenza simmetrica, crea un NUOVO set

==,!=

bool

Controlla se due insiemi sono uguali o differenti

len

[17]:
len( {'a','b','c'}  )
[17]:
3
[18]:
len( set() )
[18]:
0

Esercizio - distinte

Data una stringa parola, scrivere del codice che

  • stampa le lettere distinte presenti in parola ordinate alfabeticamente (senza le quadre!), assieme al loro numero

  • stampa il numero di lettere duplicate trovate in totale

Esempio 1 - data:

parola = "ababbbbcdd"

dopo il tuo codice deve stampare

parola     : ababbbbcdd
4 distinte : a,b,c,d
6 duplicate

Esempio 2 - data:

parola = "cccccaaabbbb"

dopo il tuo codice deve stampare

parola     : cccccaaabbbb
3 distinte : a,b,c
9 duplicate
Mostra soluzione
[19]:
# scrivi qui


parola     : ababbbbcdd
4 distinte : a,b,c,d
6 duplicate

Unione

L’operatore di unione | (detto pipe) produce un NUOVO insieme contenente tutti gli elementi del primo e del secondo insieme.

eiu3

[20]:
{'a','b','c'} | {'b','c','d','e'}
[20]:
{'a', 'b', 'c', 'd', 'e'}

Notiamo che non ci sono elementi duplicati

ESERCIZIO: E se usiamo il +? Prova a scrivere in una cella {'a','b'} + {'c','d','e'}. Cosa succede?

Mostra soluzione
[21]:
# scrivi qui


DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {'a','d','b'}|{'a','b','c'}
    
  2. {'a'}|{'a'}
    
  3. {'a'|'b'}
    
  4. {1|2|3}
    
  5. {'a'|'b'|'a'}
    
  6. {{'a'}|{'b'}|{'a'}}
    
  7. [1,2,3] | [3,4]
    
  8. (1,2,3) | (3,4)
    
  9. "abc" | "cd"
    
  10. {'a'} | set(['a','b'])
    
  11. set(".".join('pacca'))
    
  12. '{a}'|'{b}'|'{a}'
    
  13. set((1,2,3))|set([len([4,5])])
    
  14. {()}|{()}
    
  15. {'|'}|{'|'}
    

DOMANDA: Dati insiemi x e y qualunque, questa espressione

len(x | y) <= len(x) + len(y)

produce:

  1. un errore (quale?)

  2. sempre True

  3. sempre False

  4. a volte True a volte False a seconda dei valori di x e y

Mostra risposta

Esercizio: tuttotranne 1

Scrivi del codice che crea un set s4 che contiene tutti gli elementi di s1 ed s2 ma non contiene gli elementi di s3.

  • Il tuo codice dovrebbe funzionare con qualunque insieme s1, s2, s3

Esempio - dati

s1 = set(['a','b','c','d','e'])
s2 = set(['b','c','f','g'])
s3 = set(['b','f'])

Dopo il tuo codice dovresti ottenere

>>> print(s4)
{'d', 'a', 'c', 'g', 'e'}
Mostra soluzione
[22]:
s1 = set(['a','b','c','d','e'])
s2 = set(['b','c','f','g'])
s3 = set(['b','f'])

# scrivi qui


Intersezione

L’operatore di intersezione & produce un NUOVO insieme contenente tutti gli elementi in comune del primo e secondo insieme

okoerioe

[23]:
{'a','b','c'} & {'b','c','d','e'}
[23]:
{'b', 'c'}

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {0}&{0,1}
    
  2. {0,1}&{0}
    
  3. set("capra") & set("campa")
    
  4. set("cba") & set("dcb")
    
  5. {len([1,2,3]),4} & {len([5,6,7])}
    
  6. {1,2}&{1,2}
    
  7. {0,1}&{}
    
  8. {0,1}&set()
    
  9. set([1,2,3,4,5][::2]) & set([1,2,3,4,5][2::2])
    
  10. {((),)}&{()}
    
  11. {(())}&{()}
    

Differenza

L’operatore di differenza - produce un NUOVO insieme contenente tutti gli elementi del primo insieme eccetto queli del secondo:

3423dde

[24]:
{'a','b','c','d'} - {'b','c','e','f','g'}
[24]:
{'a', 'd'}

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {3,4,2}-2
    
  2. {1,2,3}-{3,4}
    
  3. '{"a"}-{"a"}'
    
  4. {1,2,3}--{3,4}
    
  5. {1,2,3}-(-{3,4})
    
  6. set("chiodo") - set("chiave")
    
  7. set("prova") - set("prova".capitalize())
    
  8. set("BarbA") - set("BARBA".lower())
    
  9. set([(1,2),(3,4),(5,6)]) - set([(2,3),(4,5)])
    
  10. set([(1,2),(3,4),(5,6)]) - set([(3,4),(5,6)])
    
  11. {1,2,3} - set()
    
  12. set() - {1,2,3}
    

DOMANDA: Dati due insiemi qualunque x e y, il seguente codice cosa produce? Un errore? E’ semplificabile?

(x & y) | (x-y)
Mostra risposta

Differenza simmetrica

La differenza simmetrica di due insiemi è la loro unione meno la loro intersezione, cioè tutti gli elementi tranne quelli in comune

kjdfslkj

In Python si può esprimere direttamente con l’operatore ^:

[25]:
{'a','b','c'} ^ {'b','c','d','e'}
[25]:
{'a', 'd', 'e'}

Verifichiamo che il risultato corrisponda alla definizione:

[26]:
s1 = {'a','b','c'}
s2 = {'b','c','d','e'}

(s1 | s2) - (s1 & s2)
[26]:
{'a', 'd', 'e'}

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {'p','e','p','p','o'} ^ {'p','a','p','p','e'}
    
  2. {'ab','cd'} ^ {'ba','dc'}
    
  3. set('brodino') ^ set('bordo')
    
  4. set((1,2,5,3,2,3,1)) ^ set((1,4,3,2))
    

DOMANDA: Dati 3 insiemi A, B, C, qual’è l’espressione per ottenere la parte in azzurro?

sewqe

Mostra risposta

DOMANDA: Se usiamo i seguenti valori nell’esercizio precedente, l’insieme che indica la parte in blu cosa conterrebbe?

A = {'a','ab','ac','abc'}
B = {'b','ab','bc','abc'}
C = {'c','ac','bc','abc'}

Una volta fatta la supposizione, prova ad eseguire la formula che hai trovato nell’esercizio precedente con i valori forniti e confronta i risultati con la soluzione.

Mostra risposta

Appartenenza

Come per tutte le sequenze, se vogliamo verificare se un elemento è contenuto in un insieme possiamo usare l’operatore in che ci ritorna un valore booleano:

[27]:
'a' in {'m','e','n','t','a'}
[27]:
True
[28]:
'z' in {'m','e','n','t','a'}
[28]:
False

in NEGLI INSIEMI E’ UN’OPERAZIONE MOLTO VELOCE

La velocità dell’operatore in NON dipende dalla dimensione dell’insieme

Questo è una differenza sostanziale rispetto alle altre sequenze già viste: se provi a cercare un elemento con in su stringhe, liste o tuple, Python potrebbe dover scorrere tutta la lista se per sfortuna l’elemento da cercare è alla fine (o non c’è proprio).

not in

Per verificare se qualcosa non appartiene ad una sequenza, possiamo usare due forme:

not in - forma 1:

[29]:
"carota" not in {"anguria","banana","mela"}
[29]:
True
[30]:
"anguria" not in {"anguria","banana","mela"}
[30]:
False

not in - forma 2

[31]:
not "carota" in {"anguria","banana","mela"}
[31]:
True
[32]:
not "anguria" in {"anguria","banana","mela"}
[32]:
False

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. 2*10 in {10,20,30,40}
    
  2. 'four' in {'f','o','u','r'}
    
  3. 'aa' in set('aa')
    
  4. 'a' in set(['a','a'])
    
  5. 'c' in (set('parco') - set('cassa'))
    
  6. 'cc' in (set('pacca') & set('zucca'))
    
  7. [3 in {3,4}, 6 in {3,4} ]
    
  8. 4 in set([1,2,3]*4)
    
  9. 2 in {len('3.4'.split('.'))}
    
  10. 4 not in {1,2,3}
    
  11. '3' not in {1,2,3}
    
  12. not 'a' in {'b','c'}
    
  13. not {} in set([])
    
  14. {not 'a' in {'a'}}
    
  15. 4 not in set((4,))
    
  16. () not in set([()])
    

DOMANDA: le seguenti espressioni sono simili. Cosa hanno in comune? Qual’è la differenza con l’ultima (oltre al fatto che è su un insieme)?

  1. 'e' in 'abcde'
    
  2. 'abcde'.find('e') >= 0
    
  3. 'abcde'.count('e') > 0
    
  4. 'e' in ['a','b','c','d','e']
    
  5. ['a','b','c','d','e'].count('e') > 0
    
  6. 'e' in ('a','b','c','d','e')
    
  7. ('a','b','c','d','e').count('e') > 0
    
  8. 'e' in {'a','b','c','d','e'}
    
Mostra risposta

Uguaglianza

Possiamo verificare se due insiemi sono uguali con l’operatore di uguaglianza ==, che dati due insiemi ritorna True se contengono elementi uguali oppure False altrimenti:

[33]:
{4,3,6} == {4,3,6}
[33]:
True
[34]:
{4,3,6} == {4,3}
[34]:
False
[35]:
{4,3,6} == {4,3,6, 'ciao'}
[35]:
False

Attento alla rimozione dei duplicati !

[36]:
{2,8} == {2,2,8}
[36]:
True

Per verificare la disuguaglianza, possiamo usare l’operatore !=:

[37]:
{2,5} != {2,5}
[37]:
False
[38]:
{4,6,0} != {2,8}
[38]:
True
[39]:
{4,6,0} != {4,6,0,2}
[39]:
True

Attenti ai duplicati e all’ordine!

[40]:
{0,1} != {1,0,0,0,0,0,0,0}
[40]:
False

DOMANDA: Guarda le seguenti espressioni, e per ciascuna cerca di indovinare quale risultato producono (o se danno errore):

  1. {2 == 2, 3 == 3}
    
  2. {1,2,3,2,1} == {1,1,2,2,3,3}
    
  3. {'aa'} == {'a'}
    
  4. set('aa') == {'a'}
    
  5. [{1,2,3}] == {[1,2,3]}
    
  6. set({1,2,3}) == {1,2,3}
    
  7. set((1,2,3)) == {(1,2,3)}
    
  8. {'aa'} != {'a', 'aa'}
    
  9. {set() != set()}
    
  10. set('scarpa') == set('capras')
    
  11. set('papa') != set('pappa')
    
  12. set('pappa') != set('reale')
    
  13. {(),()} == {(())}
    
  14. {(),()} != {(()), (())}
    
  15. [set()] == [set(),set()]
    
  16. (set('gosh') | set('posh')) == (set('shopping') - set('in'))
    

Metodi simili agli operatori

Vi sono metodi analoghi agli operatori |, &, -, ^ che creano un NUOVO set.

NOTA: diversamente dagli operatori, questi metodi accettano come parametro una qualsiasi sequenza, non solo insiemi:

Metodo

Risultato

Descrizione

Operatore analogo

set.union(seq)

set

unione, crea un NUOVO set

|

set.intersection(seq)

set

intersezione, crea un NUOVO set

&

set.difference(seq)

set

differenza, crea un NUOVO set

-

set.symmetric_difference(seq)

set

differenza simmetrica, crea un NUOVO set

^

Metodi che MODIFICANO il primo insieme su cui sono chiamati (e ritornano None!):

Metodo

Risultato

Descrizione

setA.update(setB)

None

unione, MODIFICA setA

setA.intersection_update(setB)

None

intersezione, MODIFICA setA

setA.difference_update(setB)

None

differenza, MODIFICA setA

setA.symmetric_difference_update(setB)

None

differenza simmetrica, MODIFICA setA

union

Guarderemo solo union/update, gli altri si comportano in modo analoghi

Con union dato un insieme e una generica sequenza (quindi non necessariamente un insieme) possiamo creare un NUOVO insieme:

[41]:
sa = {'g','a','r','a'}
[42]:
la = ['a','g','r','a','r','i','o']
[43]:
sb = sa.union(la)
[44]:
sb
[44]:
{'a', 'g', 'i', 'o', 'r'}

ESERCIZIO: con union possiamo usare sequenze arbitrarie, invece con gli operatori no. Prova a scrivere {1,2,3} | [2,3,4] e guarda cosa succede.

Mostra soluzione
[45]:
# scrivi qui


Possiamo verificare che union crei un nuovo insieme con Python Tutor:

[46]:
sa = {'g','a','r','a'}
la = ['a','g','r','a','r','i','o']
sb = sa.union(la)

jupman.pytut()
[46]:

update

Se vogliamo invece MODIFICARE il primo insieme, possiamo utilizzare i metodi che terminano con la parola update:

[47]:
sa = {'g','a','r','a'}
[48]:
la = ['a','g','r','a','r','i','o']
[49]:
sa.update(la)
[50]:
print(sa)
{'r', 'i', 'o', 'g', 'a'}

DOMANDA: che cosa ha ritornato la chiamata ad update?

Mostra risposta

Guardiamo che è successo con Python Tutor - per evidenziare cosa è stato ritornato da update aggiungiamo anche un x =:

[51]:
sa = {'g','a','r','a'}
la = ['a','g','r','a','r','i','o']
x = sa.update(la)
print(sa)
print(x)

jupman.pytut()
{'r', 'i', 'o', 'g', 'a'}
None
[51]:

DOMANDA: Guarda i seguenti pezzi di codice, e per ciascuno cerca di indovinare quale risultato producono (o se danno errore):

  1. set('case').intersection('sebo') == 'se'
    
  2. set('naso').difference('caso')
    
  3. s = {1,2,3}
    s.intersection_update([2,3,4])
    print(s)
    
  4. s = {1,2,3}
    s = s & [2,3,4]
    
  5. s = set('cartone')
    s = s.intersection('parto')
    print(s)
    
  6. sa = set("mastice")
    sb = sa.difference("mastro").difference("collo")
    print(sa)
    print(sb)
    
  7. sa = set("mastice")
    sb = sa.difference_update("mastro").difference_update("collo")
    print(sa)
    print(sb)
    
[ ]:

Esercizio - tuttotranne 2

Dati i set s1, s2 e s3, scrivere del codice che MODIFICA s1 in modo che contenga anche gli elementi di s2 ma non contenga gli elementi di s3.

  • Il tuo codice dovrebbe funzionare con qualunque insieme s1, s2, s3

  • NON creare nuovi set

Esempio - dati

s1 = set(['a','b','c','d','e'])
s2 = set(['b','c','f','g'])
s3 = set(['b','f'])

Dopo il tuo codice dovresti ottenere

>>> print(s1)
{'a', 'g', 'e', 'd', 'c'}
Mostra soluzione
[52]:
s1 = set(['a','b','c','d','e'])
s2 = set(['b','c','f','g'])
s3 = set(['b','f'])

# scrivi qui


{'e', 'd', 'c', 'g', 'a'}

Altri metodi

Metodo

Risultato

Descrizione

set.add(el)

None

aggiunge l’elemento specificato - se già presente non fa nulla)

set.remove(el)

None

rimuove l’elemento specificato - se non presente solleva errore

set.discard(el)

None

rimuove l’elemento specificato - se non presente non fa nulla

set.pop()

obj

rimuove un elemento arbitrario dall’insieme e lo ritorna

set.clear()

None

rimuove tutti gli elementi

setA.issubset(setB)

bool

verifica se setA è un sottoinsieme di setB

setA.issuperset(setB)

bool

verifica se setA contiene tutti gli elementi di setB

setA.isdisjoint(setB)

bool

verifica se setA non ha elementi in comune con setB

add

Dato un insieme, possiamo aggiungergli un elemento con il metodo .add:

[53]:
s = {3,7,4}
[54]:
s.add(5)
[55]:
s
[55]:
{3, 4, 5, 7}

Se aggiungiamo lo stesso elemento due volte, non accade nulla:

[56]:
s.add(5)
[57]:
s
[57]:
{3, 4, 5, 7}

DOMANDA: Se scriviamo questo codice, che risultato otteniamo?

s = {'a','b'}
s.add({'c','d','e'})
print(s)
  1. stampa {'a','b','c','d','e'}

  2. stampa {{'a','b','c','d','e'}}

  3. stampa {'a','b',{'c','d','e'}}

  4. un errore (quale?)

Mostra risposta

DOMANDA: Guarda il codice seguente, che risultato produce?

x = {'a','b'}
y = set(x)
x.add('c')
print('x=',x)
print('y=',y)
  1. un errore (quale?)

  2. x e y saranno uguali (come?)

  3. x e y saranno diversi (come?)

Mostra risposta
[58]:
x = {'a','b'}
y = set(x)
x.add('c')

jupman.pytut()
[58]:

remove

Il metodo remove toglie un elemento specificato dall’insieme. Se non esiste, produce un errore:

[59]:
s = {'a','b','c'}
[60]:
s.remove('b')
[61]:
s
[61]:
{'a', 'c'}
[62]:
s.remove('c')
[63]:
s
[63]:
{'a'}
s.remove('z')

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-266-a9e7a977e50c> in <module>
----> 1 s.remove('z')

KeyError: 'z'

Esercizio - bababiba

Data una stringa scritta di esattamente 4 sillabe da due caratteri ciascuna, creare un insieme s che contenga delle tuple con 2 caratteri ciascuna. Ogni tupla deve rappresentare una sillaba presa da scritta.

  • per aggiungere elementi all’insieme, usa solo add

  • il tuo codice deve funzionare con qualunque scritta da 4 bisillabe

Esempio 1 - data:

scritta = "bababiba"

dopo il tuo codice, deve risultare:

>>> print(s)
{('b', 'a'), ('b', 'i')}

Esempio 2 - data:

scritta = "rubareru"

dopo il tuo codice, deve risultare:

>>> print(s)
{('r', 'u'), ('b', 'a'), ('r', 'e')}
Mostra soluzione
[64]:
scritta = "bababiba"
#scritta = "rubareru"

# scrivi qui


discard

Il metodo discard toglie un elemento specificato dall’insieme. Se non esiste, non fa nulla:

[65]:
s = {'a','b','c'}
[66]:
s.discard('a')
[67]:
s
[67]:
{'b', 'c'}
[68]:
s.discard('c')
[69]:
s
[69]:
{'b'}
[70]:
s.discard('z')
[71]:
s
[71]:
{'b'}

Esercizio - spazzatura

✪✪ Un impianto di processamento rifiuti riceve un carico di spazzatura, che rappresentiamo come insieme di stringhe:

spazzatura = {'alcheni','verdura','mercurio','carta'}

Per rimuovere gli elementi contaminanti che potrebbero essere presenti (NOTA: non sempre sono presenti !), l’impianto ha esattamente 3 filtri (come lista di stringhe) che applicherà in serie alla spazzatura:

filtri = ['cadmio','mercurio','alcheni']

Per ogni filtro applicato, si vuole vedere lo stato della spazzatura processata, per vedere se il filtro ha effettivamente rimosso il contaminante (se presente)

Alla fine, si vuole anche stampare tutti e soli i contaminanti che sono stati effettivamente rimossi (mettili come insieme nella variabile separati)

  • NON usare comandi if

  • NON serve usare cicli (il numero di filtri è fisso a 3, puoi usare copia e incolla di codice)

  • Il tuo codice deve funzionare per qualsiasi lista filtri di 3 elementi e qualsiasi insieme spazzatura

Esempio - dati:

filtri = ['cadmio','mercurio','alcheni']
spazzatura = {'alcheni','verdura','mercurio','carta'}

Dopo il tuo codice, deve mostrare:

spazzatura iniziale: {'carta', 'verdura', 'mercurio', 'alcheni'}
Applico filtro per cadmio : {'carta', 'verdura', 'mercurio', 'alcheni'}
Applico filtro per mercurio : {'carta', 'verdura', 'alcheni'}
Applico filtro per alcheni : {'carta', 'verdura'}

Contaminanti separati: {'mercurio', 'alcheni'}
Mostra soluzione
[72]:
filtri = ['cadmio','mercurio','alcheni']
spazzatura = {'alcheni','verdura','mercurio','carta'}
separati = spazzatura.intersection(filtri) # crea un NUOVO insieme

# scrivi qui


spazzatura iniziale: {'alcheni', 'verdura', 'carta', 'mercurio'}
Applico filtro per cadmio : {'alcheni', 'verdura', 'carta', 'mercurio'}
Applico filtro per mercurio : {'alcheni', 'verdura', 'carta'}
Applico filtro per alcheni : {'verdura', 'carta'}

Contaminanti separati: {'alcheni', 'mercurio'}

issubset

Per verificare se tutti gli elementi di un insieme sa sono contenuti in un altro insieme sb possiamo scrivere sa.issubset(sb). Esempi:

[73]:
{2,4}.issubset({1,2,3,4})
[73]:
True
[74]:
{3,5}.issubset({1,2,3,4})
[74]:
False

ATTENZIONE: l’insieme vuoto è sempre considerato un sottoinsieme di un qualsiasi insieme

[75]:
set().issubset({3,4,2,5})
[75]:
True

issuperset

Per verificare se un insieme sacontiene tutti gli elementi di un altro insieme sb possiamo scrivere sa.issuperset(sb). Esempi:

[76]:
{1,2,3,4,5}.issuperset({1,3,5})
[76]:
True
[77]:
{1,2,3,4,5}.issuperset({2,4})
[77]:
True
[78]:
{1,2,3,4,5}.issuperset({1,3,5,7,9})
[78]:
False

ATTENZIONE: l’insieme vuoto è sempre considerato un sottoinsieme di un qualsiasi insieme

[79]:
{1,2,3,4,5}.issuperset({})
[79]:
True

isdisjoint

Un insieme è disgiunto da un altro se non ha alcun elemento in comune, per verificarlo possiamo usare il metodo isdisjoint:

[80]:
{1,3,5}.isdisjoint({2,4})
[80]:
True
[81]:
{1,3,5}.isdisjoint({2,3,4})
[81]:
False

DOMANDA: Dato un insieme qualsiasi x, cosa produce la seguente espressione?

x.isdisjoint(x)
  1. un errore (quale?)

  2. sempre True

  3. sempre False

  4. True o False a seconda del valore di x

Mostra risposta

Esercizio - matrioska

✪✪ Data una lista insiemi di esattamente 4 insiemi, la definiamo a matrioska se ogni insieme contiene tutti gli elementi del precedente insieme (più eventualmente altri). Scrivi del codice che STAMPA True se la sequenza è a matrioska, altrimenti STAMPA False.

  • NON usare if

  • il tuo codice deve funzionare per qualunque sequenza di esattamente 4 insiemi

  • SUGGERIMENTO: puoi creare una lista di 3 booleani che verificano se un set è contenuto nel successivo…

Esempio 1 - data :

insiemi = [{'a','b'},
           {'a','b','c'},
           {'a','b','c','d','e'},
           {'a','b','c','d','e','f','g','h','i'}]

dopo il tuo codice, deve stampare:

La sequenza è a matrioska? True

Esempio 2 - data :

insiemi = [{'a','b'},
           {'a','b','c'},
           {'a','e','d'},
           {'a','b','d','e'}]

dopo il tuo codice, deve stampare:

La sequenza è a matrioska? False
Mostra soluzione
[82]:
insiemi = [{'a','b'},
           {'a','b','c'},
           {'a','b','c','d','e'},
           {'a','b','c','d','e','f','g','h','i'}]


#insiemi = [{'a','b'},
#           {'a','b','c'},
#           {'a','e','d'},
#           {'a','b','d','e'}]


# scrivi qui


Esercizi con le funzioni

ATTENZIONE: Gli esercizi seguenti richiedono di conoscere:

Se sei alle prime armi con la programmazione, ti conviene saltarli e ripassare in seguito

sillabe

Scrivere una funzione sillabe che data una stringa parola costituita solo da bisillabe e un insieme trovate passato alla funzione, trova tutte le bisillabe distinte e le mette nell’insieme trovate.

  • NOTA: la funzione sillabe NON ritorna nulla !

Esempio 1:

>>> trovate = set()
>>> sillabe("banana", trovate)
>>> print(trovate)
{'an', 'ba'}

Esempio 2:

>>> trovate = set()
>>> sillabe("bonobo", trovate)
>>> print(trovate)
{'bo', 'on'}
Mostra soluzione
[83]:
# scrivi qui


distingui

✪✪ Scrivere una funzione distingui che data una lista listona contenente sottoliste di due caratteri ciascuna, RITORNA una NUOVA LISTA contenente tutte le sottoliste distinte (ignorando quindi le sottoliste duplicate)

  • la lista ritornata deve avere gli elementi nello stesso ordine in cui li si è trovati in listona

  • per sapere velocemente se una sottolista è già stata incontrata o meno, usare un insieme

  • NON effettuare ricerche in liste (quindi niente count, index, in in liste - sono lenti) !

  • NON effettuare rimozioni da liste (quindi niente remove da liste - è lenta) !

  • SUGGERIMENTO: le liste sono mutabili , possiamo metterle in un insieme? Se non è possibile, come possiamo fare?

Esempio:

>>> listona= [ ['d','d'],['a','b'],['d','d'],['c','a'],['c','a'],['d','d'],['a','b'] ]
>>> print(distingui( listona))
[['d', 'd'], ['a', 'b'], ['c', 'a']]
#NOTA: la variabile listona NON deve essere modificata:
>>> print(listona)
[ ['d','d'],['a','b'],['d','d'],['c','a'],['c','a'],['d','d'],['a','b'] ]
Mostra soluzione
[84]:
# scrivi qui


Verifica comprensione

ATTENZIONE

Gli esercizi che segueno contengono dei test con gli assert. Per capire come svolgerli, leggi prima Gestione errori e testing

Esercizio - intersectron

intersectron

Dati una lista insiemi contenente un numero arbitrario di insiemi, RITORNA un NUOVO insieme che contiene gli elementi comuni a tutti gli insiemi.

Per risolvere l’esercizio, si può intersecare un insieme alla volta con un ciclo for (lento) oppure la tecnica descritta qui (breve ed efficace).

  • prova a risolvere in entrambi i modi

  • ATTENTO alla lista vuota !

  • il tuo codice deve funzionare con un qualsiasi numeri di insiemi (l’immagine è solo un esempio)

Mostra soluzione
[85]:
def inter_for(insiemi):

    raise Exception('TODO IMPLEMENT ME !')

# INIZIO TEST - NON TOCCARE !
assert inter_for([]) == set()
assert inter_for([set(),set()]) == set()
assert inter_for([set(),set(),set()]) == set()
assert inter_for([{'a'},{'a'},{'a'}]) == {'a'}
assert inter_for([{'a','b'},{'b'},{'b'}]) == {'b'}
assert inter_for([{'a'},{'a','b'},{'a'}]) == {'a'}
assert inter_for([{'c'},{'c'},{'c','b'}]) == {'c'}
assert inter_for([{'a','b'},{'a','b'},{'a','b'}]) == {'a','b'}
assert inter_for([{'a','b','c'},{'a','b','c','d'},{'b','c','d'}, {'b','c'}]) == {'b','c'}
# verifica che non abbiamo modificato gli insiemi di input
s = {'a','b'}
assert inter_for([s,{'b','c'}]) == {'b'}
assert s == {'a','b'}
# FINE TEST
Mostra soluzione
[86]:
def inter_fast(insiemi):

    raise Exception('TODO IMPLEMENT ME !')

# INIZIO TEST - NON TOCCARE !
assert inter_fast([]) == set()
assert inter_fast([set(),set()]) == set()
assert inter_fast([set(),set(),set()]) == set()
assert inter_fast([{'a'},{'a'},{'a'}]) == {'a'}
assert inter_fast([{'a','b'},{'b'},{'b'}]) == {'b'}
assert inter_fast([{'a'},{'a','b'},{'a'}]) == {'a'}
assert inter_fast([{'c'},{'c'},{'c','b'}]) == {'c'}
assert inter_fast([{'a','b'},{'a','b'},{'a','b'}]) == {'a','b'}
assert inter_fast([{'a','b','c'},{'a','b','c','d'},{'b','c','d'}, {'b','c'}]) == {'b','c'}
# verifica che non abbiamo modificato gli insiemi di input
s = {'a','b'}
assert inter_fast([s,{'b','c'}]) == {'b'}
assert s == {'a','b'}
# FINE TEST