Stringhe 3 - metodi

Scarica zip esercizi

Naviga file online

Ogni tipo di dati ha associati dei metodi particolari per quel tipo, vediamo quelli associati al tipo stringa (str)

ATTENZIONE: Quando i metodi sulle stringhe generano una stringa, questa è SEMPRE NUOVA

L’oggetto stringa originale non viene MAI modificato (perchè le stringhe sono immutabili).

Metodi semplici

Risultato

Metodo

Significato

str

str.upper()

Ritorna la stringa con tutti i caratteri maiuscoli

str

str.lower()

Ritorna la stringa con tutti i caratteri minuscoli

str

str.capitalize()

Ritorna la stringa con il primo carattere maiuscolo

bool

str.startswith(str)

Controlla se la stringa inizia con un’altra

bool

str.endswith(str)

Controlla se la stringa finisce con un’altra

bool

str.isalpha(str)

Controlla se tutti i caratteri sono alfabetici

bool

str.isdigit(str)

Controlla se tutti i caratteri sono cifre

bool

str.isupper()

Controlla se tutti i caratteri sono minuscoli

bool

str.islower()

Controlla se tutti i caratteri sono maiuscoli

Metodi di ricerca

Le stringhe mettono a disposizione diversi metodi per effettuare ricerche e e trasformarle in nuove stringhe, 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!

Risultato

Metodo

Significato

str

str.strip(str)

Rimuove stringhe dai lati

str

str.lstrip(str)

Rimuove stringhe da sinistra

str

str.rstrip(str)

Rimuove stringhe da destra

int

str.count(str)

Conta il numero di occorrenze di una sottostringa

int

str.find(str)

Ritorna la prima posizione di una sottostringa a partire da sinistra

int

str.rfind(str)

Ritorna la prima posizione di una sottostringa a partire da destra

str

str.replace(str, str)

Sostituisce sottostringhe

Che fare

  • scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:

strings
    strings1.ipynb
    strings1-sol.ipynb
    strings2.ipynb
    strings2-sol.ipynb
    strings3.ipynb
    strings3-sol.ipynb
    strings4.ipynb
    strings4-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 strings1.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

Esempio - upper

Un metodo è una funzione di un oggetto che prende in ingresso l’oggetto a cui è applicata e vi fa dei calcoli.

Il tipo stringa (str) ha metodi predefiniti come str.upper() che possono essere applicati agli oggetti stringa (es: 'ciao' è un oggetto stringa).

Il metodo str.upper() prende la stringa su cui è applicato e crea una NUOVA stringa in cui tutti i caratteri sono in maiuscolo. Per applicare un metodo come str.upper() al particolare oggetto stringa 'ciao', dobbiamo scrivere

'ciao'.upper()

cioè dobbiamo prima scrivere l’oggetto su cui applicare il metodo ('ciao'), poi un punto . , quindi il nome del metodo seguito da parentesi tonde. Le tonde possono contenere ulteriori parametri a seconda del metodo.

Esempi:

[2]:
'ciao'.upper()
[2]:
'CIAO'
[3]:
'prova'.upper()
[3]:
'PROVA'

ATTENZIONE: come TUTTI i metodi delle stringhe, l’oggetto stringa originale su cui è chiamato NON viene modificato.

Esempio:

[4]:
x = "ciao"
y = x.upper()    #  genera una NUOVA stringa e la associa alla variabile y
[5]:
x     # la variabile x è ancora associata alla vecchia stringa
[5]:
'ciao'
[6]:
y     # la variabile y è associata alla nuova stringa
[6]:
'CIAO'

Guarda lo stesso esempio in Python Tutor:

[7]:
x = "ciao"
y = x.upper()
print(x)
print(y)

jupman.pytut()
ciao
CIAO
[7]:

Esercizio - cammina

Scrivere del codice che data una stringa x (per es: x='cammina') stampa due volta la riga

cammina CAMMINA cammina CAMMINA
cammina CAMMINA cammina CAMMINA
  • NON creare nuove variabili

  • il tuo codice deve funzionare con qualsiasi stringa

[8]:
x = 'cammina'

print(x, x.upper(), x, x.upper())
print(x, x.upper(), x, x.upper())
cammina CAMMINA cammina CAMMINA
cammina CAMMINA cammina CAMMINA

Help: Se non sei sicuro riguardo a un metodo (per esempio strip), puoi chiedere aiuto a Python in questo modo:

ATTENZIONE: con help dopo il nome del metodo NON ci sono parentesi !!

[9]:
help("ciao".strip)

Help on built-in function strip:

strip(chars=None, /) method of builtins.str instance
    Return a copy of the string with leading and trailing whitespace removed.

    If chars is given and not None, remove characters in chars instead.

Metodo lower

Ritorna la stringa con tutti i caratteri minuscoli

[10]:
stringa = "ciAo MonDo"

altra_stringa = stringa.lower()

print(altra_stringa)

ciao mondo
[11]:
print(stringa)  # non è cambiata
ciAo MonDo

Esercizio - lowermezzo

Scrivi del codice che data una stringa qualsiasi x di lunghezza dispari, stampa una nuova stringa uguale a x eccetto al carattere in mezzo che deve essere in minuscolo.

  • Il tuo codice deve funzionare con qualunque stringa !

  • SUGGERIMENTO: per calcolare la posizione del carattere in mezzo, usa la divisione intera con l’operatore //

Esempi:

Dato

x = 'ASCENSORE'

deve stampare

ASCEnSORE

Dato

x = 'LAMPADA'

deve stampare

LAMpADA

Mostra soluzione
[12]:

    #012345678
x = 'ASCENSORE'
k = len(x) // 2

# scrivi qui


Metodo capitalize

Il metodo capitalize() crea una NUOVA stringa avente solo il PRIMO carattere in maiuscolo:

[13]:
"ciao".capitalize()
[13]:
'Ciao'
[14]:
"mondo".capitalize()
[14]:
'Mondo'
[15]:
x = 'capra'
y = 'capra'.capitalize()
[16]:
x      #  x rimane associata al vecchio valore
[16]:
'capra'
[17]:
y      #  y viene associata alla nuova stringa
[17]:
'Capra'

Esercizio - Vostra Eccellenza

Scrivere del codice che date due stringhe qualsiasi x e y restituisce le due stringhe concatenate, separandole con uno spazio ed entrambe tutte in minuscolo eccetto le rispettive prime lettere che devono essere maiuscole.

Esempio 1 - dati:

x = 'vosTRA'
y = 'ecCeLLeNza'

deve stampare:

Vostra Eccellenza

Esempio 2 - dati:

x = 'sUa'
y = 'maEStà'

deve stampare:

Sua Maestà
Mostra soluzione
[18]:

x,y = 'vosTRA', 'ecCeLLeNza'
#x,y = 'sUa', 'maEStà'

# scrivi qui


Metodo startswith

str.startswith prende come parametro una stringa e ritorna True se la stringa prima del punto inizia con la stringa passata come parametro. Esempio:

[19]:
"il cane abbaia nella strada".startswith('il cane')
[19]:
True
[20]:
"il cane abbaia nella strada".startswith('abbaia')
[20]:
False
[21]:
"il cane abbaia nella strada".startswith('IL CANE')  # le maiuscole sono diverse dalle minuscole
[21]:
False
[22]:
"IL CANE ABBAIA SULLA STRADA".startswith('IL CANE')  # le maiuscole sono diverse dalle minuscole
[22]:
True

Esercizio - per Giove

Scrivere del codice che date tre stringhe qualsiasi x e y e z, stampa True se entrambe x e y iniziano con la stringa z, altrimenti stampa False

Esempi 1 - Dati:

x = 'per Giove'
y = 'per Zeus'
z = 'per'

deve stampare

True

Esempio 2 - Dati:

x = 'per Giove'
y = 'per Zeus'
z = 'da'

deve stampare

False

Esempio 3 - Dati:

x = 'da Giove'
y = 'per Zeus'
z = 'per'

deve stampare

False
Mostra soluzione
[23]:

x = 'per Giove'
y = 'per Zeus'
z = 'per'

# scrivi qui


Metodo endswith

str.endswith prende come parametro una stringa e ritorna True se la stringa prima del punto finisce con la stringa passata come parametro. Esempio:

[24]:
"I miei più cari saluti".endswith('cari saluti')
[24]:
True
[25]:
"I miei più cari saluti".endswith('cari')
[25]:
False
[26]:
"I miei più cari saluti".endswith('SALUTI')  # le maiuscole sono diverse dalle minuscole
[26]:
False
[27]:
"I MIEI PIU' CARI SALUTI".endswith('SALUTI')  # le maiuscole sono diverse dalle minuscole
[27]:
True

Esercizio - Snobbonis

Dati nomi di coppie marito e moglie, scrivi del codice che stampa True se condividono il cognome, False altrimenti.

  • assumi che il cognome sia sempre alla stessa posizione

  • il tuo codice deve funzionare per qualsiasi coppia marito moglie

Mostra soluzione
[28]:

                  #0123456789               #0123456789
marito, moglie = 'Antonio  Snobbonis',     'Carolina Snobbonis'   # True
#marito, moglie = 'Camillo  De Spaparanzi', 'Matilda  Degli Agi'  # False

# scrivi qui


Metodo isalpha

Il metodo isalpha ritorna True se tutti i caratteri nella stringa sono alfabetici:

[29]:
'BarrieraCorallina'.isalpha()
[29]:
True

I numeri non sono considerati alfabetici:

[30]:
'Route 666'.isalpha()
[30]:
False

Nota che le spaziature (i cosiddetti blank) non sono alfabetiche:

[31]:
'Barriera Corallina'.isalpha()
[31]:
False

… nè la punteggiatura:

[32]:
'!'.isalpha()
[32]:
False

… e neanche strani caratteri Unicode:

[33]:
'♥'.isalpha()
[33]:
False
[34]:
''.isalpha()
[34]:
False

Esercizio - Combattiamo gli hacker

Come è noto nei piani bassi dell’Interpol, gli hacker internazionali comunicano usando una lingua ricca di slang chiamata Leet. Tuttavia questa moda si sta diffondendo anche nelle scuole, dove si viene considerati K001 (cool) se si sa comunicare in questa scomoda maniera. La base è cercare di sostituire alle lettere dei numeri durante la scrittura. ( Qui una guida completa )

1 -> i
2 -> z
3 -> e
4 -> h, a, y
etc

Scriviamo un codice che controlla le parole usate dagli studenti per evitare che si esprimano in questa maniera, che Dante di sicuro disapprova!

  • Le parole verranno inserite di volta in volta nella variabile parola

  • Il codice deve essere generico, valido per tutte le parole

  • Devi restituire True se la parola è incriminata, contiene numeri al posto di lettere

  • Devi restituire False se la parola è scritta bene e non c’è bisogno di ramanzine agli studenti

Mostra soluzione
[35]:

parola = 'H4ck3r'    # True
#parola = 'Hacker'   # False
#parola = 'K001'     # True
#parola = 'Cool'     # False

# scrivi qui


Metodo isdigit

Il metodo isdigit ritorna True se una stringa è solo composta di cifre:

[36]:
'391'.isdigit()
[36]:
True
[37]:
'400m'.isdigit()
[37]:
False

Le notazioni a virgola mobile e scientifica non sono riconosciute:

[38]:
'3.14'.isdigit()
[38]:
False
[39]:
'4e29'.isdigit()
[39]:
False

Esercizio - Vendere numeri

La multinazionale ToxiCorp è riuscita a mettere le mani su un tesoro di dati personali di ignari utenti, e ti propone di analizzarli per poi vendere informazioni private sul mercato nero al miglior offerente. L’offerta ti pare questionabile, ma pagano bene, perciò accetti.

Occorre capire che dati sono e come catalogarli. Tra i tanti hai trovato una serie di stringhe che sembrano dei numeri di telefono.

Ogni numero dovrebbe essere così composto:

+ [prefisso nazionale 39] [10 numeri]

Scrivi del codice che stampa True se la stringa è un numero telefonico, False altrimenti

  • Dentro telefono metti uno alla volta i numeri che hai trovato

  • Il codice deve essere generico, valido per tutti i numeri

Mostra soluzione
[40]:


telefono = '+392574856985'    # True
#telefono = '395851256954'    # False (manca il '+')
#telefono = '++7485125874'    # False (manca il prefisso)
#telefono = '+39333457Ciao'   # False (mi pare ovvio :D )
#telefono = "+3912"           # False (troppo corto)
#telefono = '+393481489945'   # True

# scrivi qui


Metodi isupper e islower

Possiamo controllare se un carattere è maiuscolo o minuscolo con i metodi isupper e islower:

[41]:
'q'.isupper()
[41]:
False
[42]:
'Q'.isupper()
[42]:
True
[43]:
'b'.islower()
[43]:
True
[44]:
'B'.islower()
[44]:
False

Funzionano anche con stringhe lunghe, controllando se tutti i caratteri soddisfano il criterio:

[45]:
'GREAT'.isupper()
[45]:
True
[46]:
'NotSoGREAT'.isupper()
[46]:
False

Nota che spaziatura in genere (i blank) e punteggiatura non sono prese in considerazione:

[47]:
'TROPPO\nGIUSTO !'.isupper()
[47]:
True

Potremmo controllare se un carattere è maiuscolo/minuscolo guardando il codice ASCII ma il miglior modo per coprire tutti gli alfabeti è usare i metodi isupper e islower, per esempio funzionano anche con lettere accentate:

[48]:
'à'.isupper()
[48]:
False
[49]:
'Á'.isupper()
[49]:
True

Esercizio - nani e GIGANTI

In un mondo fantasy eccitante e sconosciuto vivono due popolazioni: si tratta dei nani e dei GIGANTI.

  • I nani amano dare nomi ai propri pargoli che contengono solo lettere minuscole.

  • I GIGANTI invece non devono nemmeno pensarci, perchè come scritto sulle tavole di GROCK i nomi dei GIGANTI possono solo avere lettere maiuscole.

Un giorno arrivò una minaccia malvagia da un regno lontano e come in tutti i clichè fu composta una compagnia. Una profezia diceva che solo una compagnia mista di GIGANTI e di nani per un totale di 4 persone avrebbe potuto sconfiggere il malvagio di turno.

  1. Scrivi del codice che controlla se quattro componenti possono comporre una compagnia valida:

  • Stampa True se i quattro nomi sono sia di nani che di GIGANTI, altrimenti se sono di una sola delle due popolazioni stampa False

  • Il codice deve essere generico, valido per tutte le stringhe

  1. Cerca dei nomi di GIGANTI e Nomi di nani e prova a metterli, facendo attenzione a tradurli con la capitalizzazione tutta minuscola / tutta maiuscola corretta, es “Jisog” non è un nome di gigante valido, va tradotto alla scrittura gigantica “JISOG”.

Mostra soluzione
[50]:

avv1, avv2, avv3, avv4 = 'gimli', 'savorlim', 'glazouc', 'hondouni'       # False
#avv1, avv2, avv3, avv4 = 'OXLOR', 'HIVAR', 'ELOR', 'SUXGROG'             # False
#avv1, avv2, avv3, avv4 = 'krakrerlig', 'GUCAM', 'SUXGROG', 'kodearen'    # True
#avv1, avv2, avv3, avv4 = 'yarnithra', 'krakrerlig', 'jandreda', 'TOVIR'  # True

# scrivi qui


Metodo strip

Elimina spazi bianchi, tab e ritorni a capo dalle estremità della stringa. In genere, questo insieme di caratteri viene definito blank

NOTA: NON rimuove i blank tra le parole della stringa! Solo quelli all’estremità destra e sinistra.

[51]:
x = ' \t\n\n\t ciao mondo \t  '   # alle estremità abbiamo messo spazi bianchi, tab e ritorni a capo
[52]:
x
[52]:
' \t\n\n\t ciao mondo \t  '
[53]:
print(x)


         ciao mondo
[54]:
len(x)   # ricorda che i caratteri speciali come \t e \n occupano 1 carattere
[54]:
20
[55]:
y = x.strip()
[56]:
y
[56]:
'ciao mondo'
[57]:
print(y)
ciao mondo
[58]:
len(y)
[58]:
10
[59]:
x      # IMPORTANTE: x è ancora associato alla vecchia stringa !
[59]:
' \t\n\n\t ciao mondo \t  '

Specificare i caratteri da rimuovere

Se vuoi che Python si limiti a rimuovere solo qualche carattere specifico, puoi specificarli in parentesi. Proviamo a specificarne solo uno:

[60]:
'salsa'.strip('s')    #  nota che la `s` interna non è rimossa
[60]:
'alsa'

Se ne specifichiamo due o più, Python rimuove tutti i caratteri che può trovare dai lati

Nota che l’ordine in cui specifichi i caratteri non conta:

[61]:
'caustic'.strip('aci')
[61]:
'ust'

ATTENZIONE: Se specifichi i caratteri, Python non proverà più a rimuovere i *blank!*

[62]:
'bouquet  '.strip('b')    # non rimuoverà gli spazi a destra!
[62]:
'ouquet  '
[63]:
'\tbouquet  '.strip('b')    # ... nè rimuoverà i blank a sinistra come il tab
[63]:
'\tbouquet  '

Secondo lo stesso principio, se specifichi uno spazio ' ', allora Python rimuoverà solo gli spazi e non cercherà gli altri blank !!

[64]:
'  attento! \t'.strip(' ')   # rimuove solo dalla sinistra!
[64]:
'attento! \t'

DOMANDA: per ciascuna delle espressioni seguenti, prova ad indovinare che risultato produce (o se da errore):

  1. '\ttumultuoso\n'.strip()
    
  2. ' a b c '.strip()
    
  3. '\ta\tb\t'.strip()
    
  4. '\\tMmm'.strip()
    
  5. 'sky diving'.strip('sky')
    
  6. 'anacondas'.strip('sad')
    
  7. '\nno way '.strip(' ')
    
  8. '\nno way '.strip('\\n')
    
  9. '\nno way '.strip('\n')
    
  10. 'salsa'.strip('as')
    
  11. '\t ACE '.strip('\t')
    
  12. ' e allora? '.strip("")
    
  13. str(-3+1).strip("+"+"-")
    

Metodo lstrip

Elimina spazi bianchi, tab e ritorni a capo dall’ estremità sinistra della stringa.

NOTA: NON rimuove i blank tra le parole della stringa! Solo quelli all’estremità sinistra.

[65]:
x = '\n \t la strada \t '
[66]:
x
[66]:
'\n \t la strada \t '
[67]:
len(x)
[67]:
16
[68]:
y = x.lstrip()
[69]:
y
[69]:
'la strada \t '
[70]:
len(y)
[70]:
12
[71]:
x       # IMPORTANTE: x è ancora associato alla vecchia stringa !
[71]:
'\n \t la strada \t '

Metodo rstrip

Elimina spazi bianchi, tab e ritorni a capo dall’ estremità destra della stringa.

NOTA: NON rimuove i blank tra le parole della stringa! Solo quelli all’estremità destra.

[72]:
x = '\n \t il faro \t '
[73]:
x
[73]:
'\n \t il faro \t '
[74]:
len(x)
[74]:
14
[75]:
y = x.rstrip()
[76]:
y
[76]:
'\n \t il faro'
[77]:
len(y)
[77]:
11
[78]:
x       # IMPORTANTE: x è ancora associato alla vecchia stringa !
[78]:
'\n \t il faro \t '

Esercizio - hatespace

Data una stringa x che può contenere dei blank (spazi, caratteri di controllo come \t e \n, …) all’inizio e alla fine, scrivi del codice che stampa la stringa senza i blank e le stringhe INIZIO e FINE alle estremità.

Esempio - dato:

x = ' \t  \n \n hatespace\n   \t \n'

stampa:

INIZIOhatespaceFINE
Mostra soluzione
[79]:

# scrivi qui


Esercizio - Bad to the bone

Hai una stringa in maiuscolo s che contiene ai lati dei caratteri che vuoi rimuovere: punteggiatura, un carattere minuscolo e dei blank. Scrivi del codice per eseguire la rimozione

Esempio - dati:

carattere = 'b'
punteggiatura = '!?.;,'
s = ' \t\n...bbbbbBAD TO THE BONE\n!'

il tuo codice dovrebbe mostrare:

'BAD TO THE BONE'
  • usa solo i metodi strip (o lstrip e rstrip) (se necessario, puoi fare chiamate ripetute)

Mostra soluzione
[80]:

carattere = 'b'
punteggiatura = '!?.;,'
s = ' \t\n...bbbbbBAD TO THE BONE\n!'

# scrivi qui


Metodo count

Il metodo count prende una sottostringa e conta quante occorrenze vi sono nella stringa prima del punto.

[81]:
"raggi astrali".count('a')
[81]:
3
[82]:
"raggi astrali".count('A')    # distingue maiuscole/minuscole
[82]:
0
[83]:
"raggi astrali".count('st')
[83]:
1

Opzionalmente, puoi passare due altri parametri per denotare un indice da quale partire a contare (incluso) e dove terminare (escluso):

[84]:
#012345678901
"raggi astrali".count('a',4)
[84]:
2
[85]:
#0123456789012
"raggi astrali".count('a',4,9)
[85]:
1

Non abusare count

ATTENZIONE: count viene spesso usato in modo errato / inefficiente

Chiediti sempre:

  1. la stringa su cui operare potrebbe contenere duplicati? Ricordati che verranno tutti conteggiati!

  2. la stringa potrebbe non contenere la sottostringa da conteggiare? Ricordati di gestire anche questo caso!

  3. count compie una ricerca in tutta la stringa, che può essere inefficiente: è proprio necessaria, o sappiamo già l’intervallo in cui cercare?

Esercizio - denaro astrale

Durante il lockdown 2020, mentre guardavi le stelle nella notte, hai cominciato a sentire… onde. Rimuginandoci sopra, hai deciso che LORO vogliono comunicare con te, perciò hai montato un antenna satellitare sul tuo tetto per ricevere messaggi dagli alieni. Dopo mesi di rumori apparentemente irrilevanti, un giorno hai finalmente ricevuto un radio-messaggio che pensi di poter tradurre. Gli alieni ovviamente stanno cercando di dirti i numeri vincenti della lotto!

Un messaggio è una sequenza di esattamente 3 diverse ripetizioni di caratteri: il numero di caratteri in ogni ripetizione è un numero che proverai alla lotteria. Inizi freneticamente a sviluppare il traduttore per mostrare questi numeri fortunati sul terminale.

Esempio - data:

s = '$$$$€€€€€!!'

dovrebbe stampare:

$ € !
4 5 2
  • IMPORTANTE: puoi assumere che tutte le sequenze abbiano caratteri *differenti*

  • NON usare cicli nè comprehension

  • per semplicità assumi che ogni sequenza di caratteri abbia al più 9 ripetizioni

Mostra soluzione
[86]:

    #01234567890      # $ € !
s = '$$$$€€€€€!!'     # 4 5 2

                      # a b c
#s = 'aaabbbbbbccc'   # 3 6 3

                      # H A L
#s = 'HAL'            # 1 1 1

# scrivi qui


Metodo find

find ritorna l’indice della prima occorrenza di qualche sottostringa data.

[87]:
#0123456789012345
'bingo bongo bong'.find('ong')
[87]:
7

Se nessuna occorrenza è trovata, ritorna -1:

[88]:
#0123456789012345
'bingo bongo bong'.find('bang')
[88]:
-1
[89]:
#0123456789012345
'bingo bongo bong'.find('Bong')    #  differenzia tra maiuscole/minuscole
[89]:
-1

Opzionalmente, puoi specificare un indice da dove iniziare a cercare (incluso):

[90]:
#0123456789012345
'bingo bongo bong'.find('ong',10)
[90]:
13

E anche dove finire (escluso):

[91]:
#0123456789012345
'bingo bongo bong'.find('g',4, 9)
[91]:
-1

Metodo rfind

Come il metodo find, ma la ricerca inizia dalla destra.

Non abusare find

ATTENZIONE: find viene spesso usato in modo errato / inefficiente

Chiediti sempre:

  1. la stringa su cui operare potrebbe contenere duplicati? Ricordati che solo il primo verrà trovato!

  2. la stringa potrebbe non contenere la sottostringa cercata? Ricordati di gestire anche questo caso!

  3. find compie una ricerca in tutta la stringa, che può essere inefficiente: è proprio necessaria, o sappiamo già l’intervallo in cui cercare?

  4. se vogliamo sapere se un carattere è in una posizione nota a priori (es 3), find non ci serve, basta scrivere stringa[3] == carattere. Usando find potrebbe trovare caratteri duplicati che stanno prima o dopo di quello che vogliamo verificare!

Esercizio - Il porto di Monkey Island

L’isola di Monkey Island ha un porto che dispone di 4 moli a cui attraccano le navi provenienti da tutto l’arcipelago. Il punto di attracco non è mai preciso, e possono esserci degli spazi arbitrari con i bordi dei moli. Vi possono anche essere navi dal nome duplicato.

  1. Supponiamo che ad ogni molo può contenere una sola nave, e vogliamo scrivere del codice che mostri True se la "The Jolly Rasta" è attraccata al molo 2 oppure False altrimenti.

Guarda i porti seguenti, e per ciascun cerca di indovinare se le righe di codice seguenti produrranno risultati corretti oppure no. Prova poi a scrivere del codice da te che non abbia i problemi che riscontrerai.

  • NON istruzioni if, cicli nè comprehension

  • NON usare liste (quindi niente split)

Mostra soluzione
[92]:

larghezza = 21  # larghezza di un molo,  INCLUSO il `|` di destra
molo = 2


# moli     :  1                    2                    3                    4
porto =      "The Mad Monkey      |  The Jolly Rasta   |  The Sea Cucumber  |LeChuck's Ghost Ship|"
#porto =     "  The Mad Monkey    |                    | The Sea Cucumber   |LeChuck's Ghost Ship|"
#porto =     "    The Mad Monkey  |The Jolly Rasta     |   The Sea Cucumber |                    |"
#porto =     "The Jolly Rasta     |                    |    The Sea Cucumber|LeChuck's Ghost Ship|"
#porto =     "                    | The Mad Monkey     |   The Jolly Rasta  |LeChuck's Ghost Ship|"
#porto =     "    The Jolly Rasta |                    | The Jolly Rasta    |   The Jolly Rasta  |"

print('La Jolly Rasta è attraccata al molo', molo, '?')
print()
print(porto)

print()
print('                     in:', 'The Jolly Rasta' in porto)

print()
print('          find su tutto:', porto.find('The Jolly Rasta') != -1)

print()
print('  find dal secondo molo:', porto.find('The Jolly Rasta', larghezza*(molo-1)) != -1)

# scrivi qui


  1. Supponiamo ora che ogni molo possa accogliere più di una nave, anche con lo stesso nome. Scrivi del codice che mostri True se una sola Grog Ship è attraccata al secondo molo, False altrimenti.

Mostra soluzione
[93]:
# moli     :  1                    2                    3                    4
porto =      "The Mad Monkey      |The Jolly Rasta     |  The Sea Cucumber  |LeChuck's Ghost Ship|"
#porto =     "The Mad Monkey      | Grog Ship Grog Ship| The Jolly Rasta    |   The Sea Cucumber "
#porto =     "   The Jolly Rasta  |   Grog Ship        | The Jolly Rasta    |   The Jolly Rasta  "
#porto =     "   Grog Ship        |   Grog Ship        |LeChuck's Ghost Ship|    Grog Ship       "
#porto =     "LeChuck's Ghost Ship|                    |   Grog Ship        |   The Jolly Rasta  "
#porto =     "The Jolly Rasta     | Grog Ship Grog Ship|       Grog Ship    |   The Jolly Rasta  "

print()
print('Una sola Grog Ship è attraccata al molo', molo, '?')
print()

# scrivi qui



Una sola Grog Ship è attraccata al molo 2 ?

Soluzione Grog Ship: False

Esercizio - banane

Durante l’esplorazione di una regione tropicale remota, un etologo scopre una popolazione di scimmie che sembra abbiano qualche concetto dei numeri. Collezionano centinaia di banane che sono poi scambiate con noci di cocco collezionate da un’altro gruppo. Per comunicare quantità fino a 999 banane, usano una serie di esattamente tre suoni gutturali. L’etologo scrive le sequenze e formula la teoria seguente: ogni suono è rappresentato da una sequenza dello stesso carattere, ripetuto un certo numero di volte. Il numero di caratteri nella prima sequenza è la prima cifra (le centinaia), il numero di caratteri nella seconda sequenza è la seconda cifra (le decine), mentre l’ultima sequenza rappresenta le unità.

Scrivi del codice che mette nella variabile banane un intero che rappresenti il numero.

Per esempio - dati:

s = 'bb bbbbb aaaa'

il tuo codice dovrebbe stampare:

>>> banane
254
>>> type(banane)
int
  • IMPORTANTE 1: sequenze differenti possono usare lo *stesso* carattere!

  • IMPORTANTE 2: non puoi assumere quali caratteri le scimmie useranno: conosci solo che ogni cifra è rappresentata da una ripetizione dello stesso carattere

  • NON usare cicli nè comprehensions

  • le scimmie non hanno cognizione dello zero

Mostra soluzione
[94]:

    #0123456789012
s = 'bb bbbbb aaaa'     # 254
#s = 'ccc cc ccc'       # 323
#s = 'vvv rrrr ww'      # 342
#s = 'cccc h jjj'       # 413
#s = '🌳🌳🌳 🍌🍌🍌🍌🍌🍌 🐵🐵🐵🐵'  # 364   (potresti ottenere *qualunque* strano carattere, anche unicode ...)

# scrivi qui


Metodo replace

str.replace prende due stringhe, e restituisce una NUOVA stringa ricavata sostituendo nella stringa su cui è chiamata tutte le occorrenze del primo parametero stringa con il secondo.

Esempio:

[95]:
"il treno percorre".replace('re', 'RO')
[95]:
'il tROno percorRO'
[96]:
"alberello bello".replace('llo', 'llini')
[96]:
'alberellini bellini'
[97]:
"parlare e brindare".replace('ARE', 'iamo')  # se cerchiamo maiuscole qua non le troveremo
[97]:
'parlare e brindare'
[98]:
"PARLARE E BRINDARE".replace('ARE', 'IAMO')  # ma qua sì
[98]:
'PARLIAMO E BRINDIAMO'

Come sempre per le stringhe, replace NON modifica la stringa su cui è chiamato:

[99]:
x = "sulla panca"
[100]:
y = x.replace('panca', 'panca la capra campa')
[101]:
y
[101]:
'sulla panca la capra campa'
[102]:
x  # IMPORTANTE: x è ancora associato alla vecchia stringa !
[102]:
'sulla panca'

E’ possile specificare fino a quante occorrenze verranno sostituite:

[103]:
'apollo fece una palla di pelle di pollo'.replace('ll', 'Zz', 3)
[103]:
'apoZzo fece una paZza di peZze di pollo'

Non abusare replace

ATTENZIONE: replace viene spesso usato in modo errato / inefficiente

Chiediti sempre:

  1. la stringa su cui operare potrebbe contenere duplicati? Ricordati che verranno tutti sostituiti!

  2. replace compie una ricerca in tutta la stringa, che può essere inefficiente: è proprio necessaria, o sappiamo già la posizione dove è presente il testo da sostituire?

Esercizio - Non aprite quella porta

DOMANDA Hai una biblioteca di libri, con etichette come G-Il padrino, R-I promessi sposi o 'H-Non aprite quella porta' composte da una un carattere che identifica il tipo (G giallo, R romanzo, H horror) seguito da - e dal titolo. Dato un libro, vuoi stampare l’etichetta completa, due punti e poi il titolo, come 'Giallo: Il padrino'. Guarda i seguenti frammenti di codice, e per ciascuno prova a scrivere delle etichette tra quelle proposte o creane altre che darebbero risultati errati (se esistono)

libro = 'G-Il padrino'
libro = 'R-I promessi sposi'
libro = 'H-Non aprite quella porta'
  1. libro.replace('G', 'Giallo: ').replace('R', 'Romanzo: ')
    
  2. libro[0].replace('G', 'Giallo: ')  \
            .replace('H', 'HORROR: ')  \
            .replace('R', 'Romanzo: ') + libro[2:]
    
  3. libro.replace('G-', 'Giallo: ').replace('R-', 'Romanzo: ')
    
  4. libro.replace('G-', 'Giallo: ',1).replace('R-', 'Romanzo: ',1)
    
  5. libro[0:2].replace('G-', 'Giallo: ').replace('R-', 'Romanzo: ') + libro[2:]
    
Mostra soluzione
[104]:

Esercizio - Il Regno degli Stringardi

La landa dei Caratterinzi è dominata col pugno di ferro dal Ducato degli Stringardi. I borghi comandati degli Stringardi si distinguono per essere monodimensionali e possono essere rappresentati come una stringa: offrono ospitalità ai duchi 'd', ai signori 's', ai vassalli 'v', e alla plebe 'p'. Al fine di separare le varie cerchie sociali da disdicevoli commistioni sono state erette delle mura |mm|. Purtroppo, il Ducato è sotto attacco dalla tribù dei beceri Replaceri, che con loro tecniche barbare e poco avvedute rischiano di radere al suolo la città. Per difendersi, gli Stringardi decidono di innalzare le mura, trasformandole da |mm| a |MM|.

  • NON usare cicli nè list comprehension

  • NON usare liste (quindi niente split)

Stringardi I: Innalza tutte le mura

Esempio - dati:

borgo = 'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'

dopo il tuo codice, deve risultare:

>>> borgo
'ppp|MM|vvvvvv|MM|sss|MM|dd|MM|sssss|MM|vvvvvv|MM|pppppp'
Mostra soluzione
[105]:

borgo =      'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
# risultato: 'ppp|MM|vvvvvv|MM|sss|MM|dd|MM|sssss|MM|vvvvvv|MM|pppppp'

# scrivi qui


Stringardi II: Mura esterne

Purtroppo la plebaglia non lavora abbastanza e non vi sono fondi per innalzare tutte le mura: innalza solo le mura all’esterno

  • NON usare if, cicli nè list comprehension

  • NON usare liste (quindi niente split)

Esempio - dati:

borgo = 'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'

dopo il tuo codice, deve risultare:

>>> borgo
'ppp|MM|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|MM|pppppp'
Mostra soluzione
[106]:

borgo =      'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
#risultato:  'ppp|MM|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|MM|pppppp'
#borgo =     '|mm|vvvvvv|mm||mm|ddddd|mm|ssvvv|mm|pp'
#risultato:  '|MM|vvvvvv|mm||mm|ddddd|mm|ssvvv|MM|pp'


# scrivi qui


Stringardi III: Potere al popolo

Una minaccia ancora più grande affligge gli Stringardi: la democrazia. A seguito del dilagare di questo male oscuro, in alcune città si sono sviluppate fazioni di destra e sinistra, che tendono a privilegiare solo alcune parti della città. Se il sentimento dominante di una città è di sinistra, tutte le abitazioni a sinistra del duca sono privilegiate a suon di dobloni, altrimenti se di destra sono privilegiate quelle a destra del duca. Quando una casa è privilegiata la lettera corrispondente viene resa in maiuscolo.

  • assumi che almeno un blocco con d sia sempre presente, e che sia unico

  • NON usare if, cicli nè list comprehension

  • NON usare liste (quindi niente split)

3.1) privilegia solo le case di sinistra

borgo = 'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'

dopo il tuo codice, deve risultare:

>>> borgo
'PPP|mm|VVVVVV|mm|SSS|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
Mostra soluzione
[107]:

borgo =      'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
# risultato: 'PPP|mm|VVVVVV|mm|SSS|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
#borgo =     '|p|ppp||p|pp|mm|vvv|vvvv|mm|sssss|mm|ddd|mm|ssss|ss|mm|vvvvvv|mm|'
# risultato: '|P|PPP||P|PP|mm|VVV|VVVV|mm|SSSSS|mm|ddd|mm|ssss|ss|mm|vvvvvv|mm|'

# scrivi qui


3.2) privilegia solo le case di destra

Esempio - dati:

borgo = 'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'

dopo il tuo codice, deve risultare:

>>> borgo
'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|SSSSS|mm|VVVVVV|mm|PPPPPP'
Mostra soluzione
[108]:

borgo =     'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|sssss|mm|vvvvvv|mm|pppppp'
#risultato: 'ppp|mm|vvvvvv|mm|sss|mm|dd|mm|SSSSS|mm|VVVVVV|mm|PPPPPP'
#borgo =    '|p|ppp||p|pp|mm|vvv|vvvv|mm|sssss|mm|ddd|mm|ssss|ss|mm|vvvvvv|p|pp|mm|'
#risultato: '|p|ppp||p|pp|mm|vvv|vvvv|mm|sssss|mm|ddd|mm|SSSS|SS|mm|VVVVVV|P|PP|mm|'

# scrivi qui


Stringardi IV: Lotte di potere

Nel tempo la famiglia ducale si è espansa e purtroppo sono nate faide spietate. A seconda della popolosità del borgo di sinistra o destra, un corrispondonete numero dei membri della famiglia più a sinistra nel palazzo ducale o più a destra ricevono supporto per attuare i loro giochi di potere. Un membro del palazzo ducale che riceve supporto diventa in maiuscolo. Ogni lettera 'p', 'v' o 's' contribuisce supporto (ma non i muri). I membri della famiglia ducale che non sono raggiunti da nessun supporto vengono trucidati dai parenti, e sostituiti con una Latin Cross Unicode

  • assumi che almeno un blocco con d sia sempre presente, e che sia unico

  • assumi che per ogni casa di sinistra/destra, vi sia almeno un duca di sinistra/destra

  • NON usare if, cicli nè list comprehension

  • NON usare liste (quindi niente split)

Esempio - dato:

borgo = 'ppp|mm|vv|mm|v|s|mm|dddddddddddddddddddddddd|mm|ss|mm|vvvvv|mm|pppp'

Dopo il tuo codice, deve stampare:

Membri della famiglia reale: 24
                di sinistra: 7
                  di destra: 11

Dopo la lotta fratricida, il nuovo borgo è:

ppp|mm|vv|mm|v|s|mm|DDDDDDD✝✝✝✝✝✝DDDDDDDDDDD|mm|ss|mm|vvvvv|mm|pppp
Mostra soluzione
[109]:

borgo =     'ppp|mm|vv|mm|v|s|mm|dddddddddddddddddddddddd|mm|ss|mm|vvvvv|mm|pppp'
#risultato: 'ppp|mm|vv|mm|v|s|mm|DDDDDDD✝✝✝✝✝✝DDDDDDDDDDD|mm|ss|mm|vvvvv|mm|pppp'  tot:24 sx:7 dx:11
#borgo =    'ppp|mm|ppp|mm|vv|mm|ss|mm|dddddddddddddddddddd|mm|ss|mm|mm|s|v|mm|p|p|'
#risultato: 'ppp|mm|ppp|mm|vv|mm|ss|mm|DDDDDDDDDD✝✝✝✝DDDDDD|mm|ss|mm|mm|s|v|mm|p|p|' tot:20 sx:10 dx:6

# scrivi qui


Altri esercizi

DOMANDA: Per ciascuna espressione di seguito, cerca di indovinare il risultato.

  1. 'gUrP'.lower() == 'GuRp'.lower()
    
  2. 'NaNo'.lower() != 'nAnO'.upper()
    
  3. 'O' + 'ortaggio'.replace('o','\t \n     ').strip() + 'O'
    
  4. 'DaDo'.replace('D','b') in 'barbados'
    

Prosegui

Trovi ulteriori esercizi nel foglio Stringhe 4