2012-01-30 6 views
8

Si tengo los siguientes valores booleanosAsegúrese de que exactamente un booleano de una lista dada sea verdadero?

const YESTERDAY = false; 
const TODAY = true; 
const TOMORROW = false; 

¿Qué código puedo escribir para asegurarse de que exactamente una es verdadera?

He intentado esto:

$x = self::YESTERDAY^self::TODAY^self::TOMORROW; 

El problema es que con las tres constantes seleccionadas a continuación true$x es true.

+0

puede poner toda la combinación usando OR condición '(AYERDAY = verdadero Y HOY = falso Y MAÑANA = falso) o (AYER = DIA Y HOY = verdadero Y MAÑANA = falso) o (AYER = DIA Y HOY = falso Y TOMORROW = true) ' –

+0

Él tiene que asegurarse de que la verdadera es una, NO AL MENOS UNA. – devdRew

Respuesta

8

$x = ((int) self::YESTERDAY) + ((int) self::TODAY) + ((int) self::TOMORROW); Luego, si $x === 1; tiene lo que necesita.

Editado:

Incluso sin conversiones de tipo (int), funciona bien, gracias a @DaveRandom, por lo que:

if (self::YESTERDAY + self::TODAY + self::TOMORROW == 1) {}, en cuanto a mí.

+0

Pensé en esto, pero sería bueno evitar todo ese procesamiento adicional, ¿hay alguna manera de hacer esto a nivel de bit? – Matthew

+0

+1 esto - parece que después de la prueba que ni siquiera necesita los moldes '(int)', sucede implícitamente. – DaveRandom

+1

Esto es mucho más ordenado que cualquiera de las otras [email protected] fue casi correcto al usar el operador XOR (^), pero desafortunadamente 'true^true^true' se evaluará como' true', porque PHP lo interpreta como '(true^true)^true', es decir' false^true ' – WildlyInaccurate

0

Así como una alternativa a la respuesta de devdRew

$x = array_count_values(array((int) self::YESTERDAY,(int) self::TODAY,(int) self::TOMORROW)); 
if (isset($x[1]) && $x[1] == 1) { 
    echo 'Only one TRUE'; 
} 
2

La manera más ordenada que se me ocurre es array_sum():

if (array_sum(array(self::YESTERDAY, self::TODAY, self::TOMORROW)) == 1) { 
    // Do something 
} 

EDITAR En realidad, todo lo que tiene que hacer es sustituir el ^ con + en su intento original, y logra lo mismo:

$x = self::YESTERDAY + self::TODAY + self::TOMORROW; 

Esto convierte $x en el número de valores TRUE. Así que para una utilización salida booleana:

$ok = self::YESTERDAY + self::TODAY + self::TOMORROW === 1; 
+0

que es bastante limpio! – Matthew

+0

En realidad, una variante de la respuesta de devdRew es la más adecuada: si reemplaza '^' por '+' en el código original, hace lo mismo, no necesita los moldes '(int)' ya que esto sucede implícitamente. – DaveRandom

+0

¡eso es aún más ordenado! – Matthew

0

puede recorrer a través de una lista de variables y se rompen cuando se encontró un segundo booleano que es cierto:

$moreThanOneTrue=false; 
$oneTrue; 
foreach ($BOOL_VAR_ARRAY as $bool) { 
    if ($bool) { 
     if($oneTrue) { 
      $moreThanOneTrue=true; 
      break; 
     } 
     $oneTrue=true; 
    } 
} 

como no es más útil cuando se tienen más de tres variables.

+0

Si hay más de 3 creo que el método 'array_sum' sería más simple que este – Matthew

+0

@Matt: Estoy de acuerdo .. – ezdazuzena

0

x devolverá verdadero si y solo si uno es verdadero y otros son falsos.

$x = ($a && !($b || $c)) || ($b && !($a || $c)) || ($c && !($a || $b)); 

Puede ser un código incorrecto, pero funciona.

0

a^b^c^(a & b & c) es la expresión que busca.

Cuestiones relacionadas