10  Estructuras de control condicionales

En algunas partes de un programa puede ser útil detenerse para elegir entre una o más opciones disponibles para continuar con la ejecución del código. Para elegir, planteamos una pregunta o evaluación lógica, cuya respuesta deberá ser VERDADERO (TRUE) o FALSO (FALSE). Según el resultado, el algoritmo seguirá ciertas acciones e ignorará otras. Estas preguntas y respuestas representan procesos de toma de decisión que conducen a diferentes caminos dentro de un programa, permitiéndonos que la solución para el problema en cuestión sea flexible y se adapte a distintas situaciones. Este tipo de estructuras de control de las instrucciones de programación reciben el nombre de condicionales (o estructuras de selección) y pueden ser simples, dobles o múltiples.

10.1 Estructuras condicionales simples

Postulan una evaluación lógica y, si su resultado es TRUE, se procede a ejecutar las acciones delimitadas entre las llaves que definen el cuerpo de esta estructura. se expresan en R con la siguiente sintaxis:

if (condición) {
    hacer esto
}

La palabra if indica el comando de evaluación lógica, condición indica la evaluación a realizar y entre llaves se detallan las instrucciones que se realizan sólo si se cumple la condición, es decir, si la evaluación resulta TRUE. Dentro de las llaves puede haber una o muchas líneas de código. Si la condición no se verifica (es FALSE), no se ejecuta ninguna acción y el programa sigue su estructura secuencial con el código que prosigue a la última llave.

El siguiente programa registra la edad de una persona y, en el caso de que sea mayor de edad, avisa que puede votar en las elecciones provinciales de Santa Fe:

# Persona A
edad <- 27
if (edad >= 18) {
    cat("Edad =", edad, "años: puede votar")
}
Edad = 27 años: puede votar
# Persona B
edad <- 15
if (edad >= 18) {
    cat("Edad =", edad, "años: puede votar")
}

# no se ejecuta ninguna acción

Notar que si bien el uso de sangrías o indentación en el código dentro de las llaves es opcional, decidimos emplearlo para facilitar la lectura y la identificación del inicio y el fin del bloque condicional. Mantener la prolijidad en nuestros programas es esencial.

10.2 Estructuras condicionales dobles

La estructura simple sólo provee un curso de acción en el caso de que la evaluación sea TRUE. La estructura doble permite especificar, además, qué se debe hacer en el caso de que le resultado sea FALSE. La sintaxis es:

if (condición) {
    hacer esto
} else {
    hacer otra cosa
}

Dentro del primer bloque de llaves se escriben las instrucciones que se ejecutan si se cumple la condición, mientras que en el segundo, luego de la expresión else (“si no”), se incluyen las que se evalúan si no se verifica la misma.

Retomamos el caso anterior para emitir un mensaje cualquiera sea la situación:

# Persona A
edad <- 27
if (edad >= 18) {
    cat("Edad =", edad, "años: puede votar")
} else {
    cat("Edad =", edad, "años: no puede votar")
}
Edad = 27 años: puede votar
# Persona B
edad <- 15
if (edad >= 18) {
    cat("Edad =", edad, "años: puede votar")
} else {
    cat("Edad =", edad, "años: no puede votar")
}
Edad = 15 años: no puede votar

10.3 Estructuras condicionales múltiples o anidadas

Permiten combinar varias estructuras condicionales para establecer controles más complejos sobre el flujo de la ejecución de las instrucciones, representando una toma de decisión múltiple. Podemos ejemplificar la sintaxis de la siguiente forma:

if (condición 1) {
    hacer esto
} else if (condición 2) {
    hacer otra cosa
} else {
    hacer otra cosa distinta
}

En la estructura anterior, hay una primera evaluación lógica. Si su resultado es TRUE, se ejecuta el código encerrado en el primer juego de llaves y el resto es ignorado. En cambio, si su resultado es FALSE, se procede a evaluar la segunda evaluación lógica, que da lugar a la ejecución del segundo bloque de código si el resultado es TRUE o del tercer bloque, si su resultado es FALSE.

El último bloque de acciones, indicado con hacer otra cosa distinta, se evaluará sólo si ninguna de las condiciones lógicas anteriores fue TRUE.

Completamos el caso de la edad y la votación, considerando la no obligatoriedad para las personas mayores:

# Persona A
edad <- 27
if (edad < 18) {
    cat("Edad =", edad, "años: no puede votar")
} else if (edad >= 70) {
    cat("Edad =", edad, "años: puede votar opcionalmente")
} else {
    cat("Edad =", edad, "años: debe votar obligatoriamente")
}
Edad = 27 años: debe votar obligatoriamente
# Persona B
edad <- 15
if (edad < 18) {
    cat("Edad =", edad, "años: no puede votar")
} else if (edad >= 70) {
    cat("Edad =", edad, "años: puede votar opcionalmente")
} else {
    cat("Edad =", edad, "años: debe votar obligatoriamente")
}
Edad = 15 años: no puede votar
# Persona C
edad <- 81
if (edad < 18) {
    cat("Edad =", edad, "años: no puede votar")
} else if (edad >= 70) {
    cat("Edad =", edad, "años: puede votar opcionalmente")
} else {
    cat("Edad =", edad, "años: debe votar obligatoriamente")
}
Edad = 81 años: puede votar opcionalmente

¿Cuál será el valor final de resultado después de ejecutar el siguiente código en R?

x <- 20
if (x < 10) {
  resultado <- x * 20
} else if (x < 20) {
  resultado <- x / 2
} else {
  resultado <- x + 100
}
resultado

resultado es igual a: .

10.4 Más ejemplos con las estructuras condicionales

10.4.1 Múltiples else if

Se pueden encadenar tantos bloques else if como sea necesario para establecer múltiples evaluaciones lógicas en cascada. Esto es útil cuando tienes varias categorías o intervalos que evaluar:

El siguiente programa evalúa una calificación numérica y asigna una categoría de desempeño:

# Ejemplo 1: nota alta
nota <- 9
if (nota < 4) {
    resultado <- "Insuficiente"
} else if (nota < 6) {
    resultado <- "Regular"
} else if (nota < 8) {
    resultado <- "Bueno"
} else if (nota < 10) {
    resultado <- "Muy Bueno"
} else {
    resultado <- "Excelente"
}
cat(resultado)
Muy Bueno
# Ejemplo 2: nota baja
nota <- 3
if (nota < 4) {
    resultado <- "Insuficiente"
} else if (nota < 6) {
    resultado <- "Regular"
} else if (nota < 8) {
    resultado <- "Bueno"
} else if (nota < 10) {
    resultado <- "Muy Bueno"
} else {
    resultado <- "Excelente"
}
cat(resultado)
Insuficiente

10.4.2 Ejemplos con operadores lógicos

Los operadores lógicos (&&, ||, !) permiten combinar múltiples condiciones en una única evaluación, lo que es especialmente útil para simplificar el código y hacerlo más legible:

El siguiente programa evalúa si una persona puede conducir según su edad y si posee licencia:

edad <- 25
tiene_licencia <- TRUE

# AND: ambas condiciones deben ser TRUE
if (edad >= 18 & tiene_licencia) {
    cat("Podés conducir")
} else {
    cat("No podés conducir")
}
Podés conducir
# OR: una de las dos condiciones basta
edad <- 16
if (edad >= 18 | tiene_licencia) {
    cat("Cumplís con algún requisito")
} else {
    cat("No cumplís con los requisitos")
}
Cumplís con algún requisito
# NOT: negación de una condición
edad <- 25
if (!(edad < 18)) {
    cat("Sos mayor de edad")
} else {
    cat("Sos menor de edad")
}
Sos mayor de edad

10.4.3 Condicionales anidadas

Es posible tener una estructura condicional dentro de otra, anidando niveles de decisión según sea necesario:

El siguiente programa verifica múltiples condiciones de forma anidada para determinar si una persona puede conducir:

edad <- 25
tiene_licencia <- TRUE

if (edad >= 18) {
    if (tiene_licencia) {
        cat("Podés conducir")
    } else {
        cat("Necesitás licencia para conducir")
    }
} else {
    cat("No podés conducir: sos menor de edad")
}
Podés conducir

Nota: El anidamiento es una herramienta poderosa, pero puede hacer el código más complejo. En muchos casos, es preferible usar operadores lógicos para simplificar y mejorar la legibilidad:

Versión anidada (más difícil de leer):

if (edad >= 18) {
    if (tiene_licencia) {
        cat("Podés conducir")
    }
}

Versión simplificada con operadores lógicos (más legible):

if (edad >= 18 && tiene_licencia) {
    cat("Podés conducir")
}

Ambas formas son válidas, pero la segunda es más clara y concisa.