if-statement - ternario - google data studio calculated fields formulas
Si la condición A coincide, la condición B debe coincidir para realizar la acción C (12)
Aunque ya hay buenas respuestas, pensé que este enfoque podría ser aún más intuitivo para alguien que es nuevo en el álgebra booleana que evaluar una tabla de verdad.
Lo primero que quiere hacer es mirar, bajo qué condiciones desea ejecutar C. Este es el caso cuando
(a & b)
.
También cuando
!a
Entonces tienes
(a & b) | !a
(a & b) | !a
.
Si quieres minimizar puedes continuar. Al igual que en la aritmética "normal", puede multiplicarse.
(a & b) | !a = (a | !a) & (b | !a)
(a & b) | !a = (a | !a) & (b | !a)
.
a |
! a siempre es cierto, por lo que puedes tacharlo, lo que te deja con el resultado minimizado:
b | !a
b | !a
.
En caso de que el orden marque la diferencia, porque desea comprobar b solo si! A es verdadero (por ejemplo, cuando! A es una comprobación de puntero nulo yb es una operación en el puntero como @LordFarquaad señaló en su comentario), puede quiero cambiar los dos.
El otro caso (/ * ... * /) siempre se ejecutará cuando c no se ejecute, por lo que podemos ponerlo en el caso else.
También vale la pena mencionar que probablemente tenga sentido de cualquier manera poner la acción c en un método.
Lo que nos deja con el siguiente código:
if (!A || B)
{
doActionC() // execute method which does action C
}
else
{
/* ... */ // what ever happens here, you might want to put it into a method, too.
}
De esta manera, también puede minimizar los términos con más operandos, lo que rápidamente se vuelve feo con las tablas de verdad. Otro buen enfoque son los mapas de Karnaugh. Pero no voy a profundizar en esto ahora.
Mi pregunta es:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
¿Es posible escribir el código de acción C una vez en lugar de dos?
¿Cómo simplificarlo?
En el concepto lógico, puede resolver este problema de la siguiente manera:
f = ab +! a
f =?
Como un problema comprobado, esto resulta en
f = !a + b
.
Hay algunas formas de probar el problema, como la tabla de verdad, el
mapa de Karnaugh
, etc.
Entonces, en los lenguajes basados en C, puede usar lo siguiente:
if(!a || b)
{
// Do action C
}
PD: Karnaugh Map también se usa para series de condiciones más complicadas. Es un método para simplificar las expresiones de álgebra booleana.
En un lenguaje con coincidencia de patrones, puede expresar la solución de manera que refleje más directamente la tabla de verdad en la respuesta de QuestionC.
match (a,b) with
| (true,false) -> ...
| _ -> action c
Si no está familiarizado con la sintaxis, cada patrón está representado por un | seguido de los valores para que coincidan con (a, b), y el guión bajo se utiliza como comodín para significar "cualquier otro valor". Dado que el único caso en el que queremos hacer algo diferente a la acción c es cuando a es verdadero yb es falso, declaramos explícitamente esos valores como el primer patrón (verdadero, falso) y luego hacemos lo que se debe hacer en ese caso. En todos los demás casos, seguimos el patrón de "comodines" y hacemos acciones c.
Extraería C a un método y luego saldría de la función lo antes posible en todos los casos.
else
cláusulas con una sola cosa al final casi siempre deben invertirse si es posible.
Aquí hay un ejemplo paso a paso:
Extracto C:
if (A) {
if (B)
C();
else
D();
} else
C();
Invierta primero
if
quiere deshacerse de
else
:
if (!A) {
C();
return;
}
if (B)
C();
else
D();
Deshazte del segundo
else
:
if (!A) {
C();
return;
}
if (B) {
C();
return;
}
D();
Y luego puede notar que los dos casos tienen el mismo cuerpo y se pueden combinar:
if (!A || B) {
C();
return;
}
D();
Las cosas opcionales para mejorar serían:
-
depende del contexto, pero si
!A || B
!A || B
es confuso, extráigalo a una o más variables para explicar la intención -
lo que sea
C()
oD()
es el caso no excepcional, debe ir al final, por lo que siD()
es la excepción, invierta el último caso
La declaración del problema:
Si la condición A coincide, la condición B debe coincidir para realizar la acción C
describe la
implication
:
A
implica
B
, una proposición lógica equivalente a
!A || B
!A || B
(como se menciona en otras respuestas):
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
Para que el código se parezca más al texto, use banderas booleanas. Si la lógica es especialmente oscura, agregue comentarios.
bool do_action_C;
// Determine whether we need to do action C or just do the "..." action
// If condition A is matched, condition B needs to be matched in order to do action C
if (/* condition A */)
{
if(/* condition B */)
do_action_C = true; // have to do action C because blah
else
do_action_C = false; // no need to do action C because blarg
}
else
{
do_action_C = true; // A is false, so obviously have to do action C
}
if (do_action_C)
{
DoActionC(); // call the function
}
else
{
...
}
Puede simplificar la declaración de esta manera:
if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments
{
do C
}
De lo contrario, coloque el código para ''C'' en una función separada y llámelo:
DoActionC()
{
....
// code for Action C
}
if (condition A)
{
if(condition B)
{
DoActionC(); // call the function
}
else
...
}
else
{
DoActionC(); // call the function
}
Su primer paso en este tipo de problemas es siempre hacer una tabla lógica.
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
Una vez que haya hecho la tabla, la solución es clara.
if (A && !B) {
...
}
else {
do action C
}
Tenga en cuenta que esta lógica, aunque más corta, puede ser difícil de mantener para futuros programadores.
Tienes dos opciones:
-
Escriba una función que realice "acción C".
-
Reorganice su lógica para que no tenga tantas sentencias if anidadas. Pregúntese qué condiciones causan la "acción C". Me parece que sucede cuando la "condición B" es verdadera o la "condición A" es falsa. Podemos escribir esto como "NO A O B". Traduciendo esto al código C, obtenemos
if (!A || B) { action C } else { ... }
Para obtener más información sobre este tipo de expresiones, sugiero buscar en Google "álgebra booleana", "lógica de predicados" y "cálculo de predicados". Estos son temas matemáticos profundos. No necesitas aprenderlo todo, solo lo básico.
También debe aprender sobre la "evaluación de cortocircuito".
Debido a esto, el orden de las expresiones es importante para duplicar exactamente su lógica original.
Mientras
B || !A
B || !A
es lógicamente equivalente, usando esto como la condición ejecutará la "acción C" cuando
B
es verdadera independientemente del valor de
A
Ugh, esto también me hizo tropezar, pero como lo
señaló Code-Apprentice,
tenemos la garantía de que debemos
do action C
o ejecutar el bloque nested-
else
, por lo que el código podría simplificarse para:
if (not condition A or condition B) {
do action C
} else {
...
}
Así es como estamos llegando a los 3 casos:
-
La
do action C
anidada en la lógica de su pregunta requería que lacondition A
y lacondition B
fuerantrue
: en esta lógica, si alcanzamos el segundo término en la declaraciónif
, sabemos que lacondition A
estrue
tanto, todo lo que necesitamos evaluar es que lacondition B
estrue
-
El bloque
else
anidado en la lógica de su pregunta requiere que lacondition A
seatrue
y lacondition B
seafalse
. La única forma en que podemos alcanzar el bloqueelse
en esta lógica sería si lacondition A
fueratrue
y lacondition B
false
-
El bloque externo en la lógica de su pregunta requiere que la
condition A
seafalse
: en esta lógica, si lacondition A
es falsa, también realizamos lado action C
Apoyos para Code-Apprentice por enderezarme aquí. Sugeriría aceptar su respuesta , ya que la presentó correctamente sin editar: /
Usar banderas también puede resolver este problema
int flag = 1;
if ( condition A ) {
flag = 2;
if( condition B ) {
flag = 3;
}
}
if(flag != 2) {
do action C
}
if((A && B ) || !A)
{
//do C
}
else if(!B)
{
//...
}