Capitolo 13 Programmazione Condizionale
Uno dei principali costrutti della programmazione sono proprio le espressioni condizionali. L’idea semplice alla base è quella di eseguire alcune operazioni o eseguire le operazioni in un certo modo in funzione di alcune condizioni. Le condizioni non sono altro che espressioni che resituiscono sempre un valore booelan ovvero TRUE
oppure FALSE
.
L’esempio classico è quello dell’ombrello, immaginate di scrivere il codice per un videogioco e avete scritto una funzione per far prendere prendere e aprire l’ombrello al vostro personaggio. Chiaramente per rendere tutto credibile, dovete far eseguire questa operazione solo quando è richiesto ovvero quando piove. In termini di programmazione, dovete prima verificare una certa condizione (la pioggia) e poi eseguire (o non eseguire) una serie di operazioni di conseguenza.
13.1 Strutture condizionali
Ci sono diverse possibilità in R, tuttavia la logica di eseguire operazioni solo quando alcune condizioni sono rispettate è sempre la stessa. La Figura 13.1 rappresenta la struttura generica di un flusso di controllo condizionale.
13.1.1 if
Struttura if
Per scrivere la struttura condizionale della Figura 13.1 si usa la seguente sintassi in R:
Esempio
- Singolo if
my_function <- function(value){
if(value > 0){
cat("Il valore è maggiore di 0\n")
}
cat("Fine funzione\n")
}
my_function(5)
## Il valore è maggiore di 0
## Fine funzione
my_function(-5)
## Fine funzione
- Multipli if
my_function <- function(value){
if(value > 0){
cat("Il valore è maggiore di 0\n")
}
if(value > 10){
cat("Il valore è maggiore di 10\n")
}
cat("Fine funzione\n")
}
my_function(5)
## Il valore è maggiore di 0
## Fine funzione
my_function(15)
## Il valore è maggiore di 0
## Il valore è maggiore di 10
## Fine funzione
my_function(-5)
## Fine funzione
13.1.2 if…else
Il semplice utilizzo di un singolo if
potrebbe non essere sufficiente in alcune situazioni. Sopratutto perchè possiamo vedere l’if
come una deviazione temporanea dallo script principale (molto chiaro nella figura 13.1) che viene imboccata solo se è vera una condizione, altrimenti lo script continua. Se vogliamo una struttura più “simmetrica” possiamo eseguire delle operazioni se la condizone è vera if
e altre per tutti gli altri scenari (else
). La Figura 13.2 mostra chiaramente questa struttura diversa nel flusso.
Struttura if
In R questo viene implementato nel seguente modo:
Esempio
- Singolo if…else
my_function <- function(value){
if(value >= 0){
cat("Il valore è maggiore di 0\n")
} else {
cat("Il valore non è maggiore di 0\n")
}
cat("Fine funzione\n")
}
my_function(5)
## Il valore è maggiore di 0
## Fine funzione
my_function(-5)
## Il valore non è maggiore di 0
## Fine funzione
- Multipli if
my_function <- function(value){
if(value > 0){
cat("Il valore è maggiore di 0\n")
} else if (value > 10){
cat("Il valore è maggiore di 10\n")
} else {
cat("Il valore non è maggiore di 0\n")
}
cat("Fine funzione\n")
}
my_function(5)
## Il valore è maggiore di 0
## Fine funzione
my_function(15)
## Il valore è maggiore di 0
## Fine funzione
my_function(-5)
## Il valore non è maggiore di 0
## Fine funzione
E’ importante capire la differenza tra usare multipli if
e else if
rispetto a utilizzare un semplice else
. Se noi vogliamo specificare un set finito di alternative, la scelta migliore e quella più chiara consiste di usere else if
perchè al contrario di else
richiede di specificare la condizione. Se invece siamo interessanti ad alcune condizioni mentre per tutto il resto applichiamo la stessa operazione, possiamo concludere il nostro flusso con un else
.
13.1.3 Nested
Oltre a concatenare una serie di if
e else if
è possibile inserire uno o più if
all’interno di un’altro. Questo permette di controllare delle condizioni che sono dipendenti dal controllo precedente e quindi non possono essere eseguite in serie.
Struttura if
Esempio
my_function <- function(value){
if(value > 0){
if(value > 10) {
cat("Il valore è maggiore di 10\n")
} else {
cat("Il valore è maggiore di 0\n")
}
} else {
cat("Il valore non è maggiore di 0\n")
}
cat("Fine funzione\n")
}
my_function(5)
## Il valore è maggiore di 0
## Fine funzione
my_function(15)
## Il valore è maggiore di 10
## Fine funzione
my_function(-5)
## Il valore non è maggiore di 0
## Fine funzione
Esercizi
Esegui i seguenti esercizi:
Definisci una funzione per assegnare un voto in base alla percentuale di rispote corrette (score) segui le seguenti indicazioni:
- score < .55 insufficiente
- .55 <= score < .65 - sufficiente
- .65 <= score < .75 - buono
- .75 <= score < .85 - distinto
- .85 <= score - ottimo
Definisci una funzione che determini se un numero è pari o dispari.
Definisci una funzione che determini se un numero è un multiplo di 3, 4, o 5.
Definisci una funzione che calcoli lo stipendio mensile considerando gli straordinari che sono retribuiti 1.5 della paga oraria normale. Utilizza come parametrile ore svolte nel mese, la paga oraria ed il tetto ore lavorative, oltre cui si contano gli straordinari.
13.2 Altri Operatori Condizionali
13.2.1 switch
L’operatore switch
è un utile alternativa quando vogliamo eseguire una porzione di codice in modo condizionale all’input senza tuttavia usare una serie di if
.
Struttura switch
In questo caso, se il valore input (my_value
) ha una corrispondenza tra i casi considerati (ad esempio case1
), il codice corrispondente (action1
) viene eseguito.
Ci sono alcune regole da considerare quando si utilizza uno switch
statement:
- se il valore inserito è una stringa, R cercherà una corrispondenza come
input == argomento
- se è presente più di una corrispondenza, viene utilizzata la prima
- non c’è la possibilità di inserire un valore di default
- se non viene trovata una corrispondenza viene restituito un valore
NULL
. Inserendo però uncase
senza un valore corrispondente, questo verra utilizzato al posto diNULL
.
13.2.2 ifelse
Gli if
, else
e else if
statements funzionano solo per un singolo valore. In altri termini non è possibile testare una stessa condizione su una serie di elementi. Nel prossimo capitolo affronteremo la programmazione iterativa che permette di ripetere una serie di operazioni. Tuttavia utilizzando la funzione ifelse()
è possibile implementare una versione vettorizzata delle operazioni condizionali.
La struttura è la seguente:
Dove:
test
è la condizione da valutare e corrisponde a quello che di solito era tra parentesi negliif
precedentiif(test){...}
yes
è il codice che viene eseguito se la condizione èTRUE
no
è il codice che viene eseguito se la condizione èFALSE
Esempio
Immaginiamo di avere un vettore di numeri che corrispondono a delle età e vogliamo eseguire qualcosa se il l’età è maggiore o minore di 18 anni, ad esempio mostrare semplicemente la scritta “maggiorenne” oppure “minorenne”. Utilizzando un semplice if
vediamo che:
age <- c(18, 19, 11, 10, 23, 55, 33, 26, 10)
if(age < 18){
print("Minorenne")
}else{
print("Maggiorenne")
}
## Warning in if (age < 18) {: the condition has length > 1 and only the first
## element will be used
## [1] "Maggiorenne"
Veniamo avvertiti che age
non è un singolo valore e che quindi solo il primo valore è utilizzato. Questo dimostra che if
non funziona su una lista di elementi. Utilizzando ifelse
invece:
ifelse(age < 18, yes = print("Minorenne"), no = print("Maggiorenne"))
## [1] "Minorenne"
## [1] "Maggiorenne"
## [1] "Maggiorenne" "Maggiorenne" "Minorenne" "Minorenne" "Maggiorenne"
## [6] "Maggiorenne" "Maggiorenne" "Maggiorenne" "Minorenne"
In questo caso l’idea è di eseguire il codice precedente per ogni valore del nostro vettore in input. Questo è possibile perchè l’operazione <
è vettorizzata.