2012-01-30 12 views
8

Se ho i seguenti booleaniAssicurarsi che esattamente un valore booleano di una determinata lista sia vero?

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

Quale codice posso scrivere per assicurarsi che esattamente un è vero?

Ho provato questo:

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

Il problema è che con tutte e tre le costanti impostate per true poi $x è true.

+0

è possibile inserire tutte le combinazioni utilizzando la condizione OR '(YESTERDAY = true AND TODAY = false AND TOMORROW = false) oppure (YESTERDAY = false AND TODAY = true AND TOMORROW = false) o (YESTERDAY = false AND TODAY = false AND TOMORROW = true) ' –

+0

Ha bisogno di essere certo che il vero sia uno ESCLUSIVO, non ALMENO UNO. – devdRew

risposta

8

$x = ((int) self::YESTERDAY) + ((int) self::TODAY) + ((int) self::TOMORROW); Quindi se $x === 1; Hai quello che ti serve.

Modificato:

Anche senza tipo calchi (int), funziona bene, grazie a @DaveRandom, quindi:

if (self::YESTERDAY + self::TODAY + self::TOMORROW == 1) {}, per quanto mi riguarda.

+0

Ho pensato a questo, ma sarebbe stato carino evitare tutta questa elaborazione extra, c'è un modo per farlo? – Matthew

+0

+1 - sembra dopo aver provato che non hai nemmeno bisogno dei cast '(int)', accade implicitamente. – DaveRandom

+1

Questo è molto più ordinato di qualsiasi altra [email protected] era quasi corretto nell'uso dell'operatore XOR (^), ma sfortunatamente 'true^true^true' valuterà' vero', perché PHP lo interpreta come '(true^true)^true', cioè 'false^true ' – WildlyInaccurate

0

Proprio come alternativa alla risposta di 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

Il modo più grazioso mi viene in mente è array_sum():

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

EDIT In realtà, tutto quello che dovete fare è sostituire il ^ con + nel tuo tentativo originale, e raggiunge la stessa cosa:

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

Questo diventa $x nel numero di valori TRUE. Così, per un uso uscita booleano:

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

che è abbastanza bello! – Matthew

+0

In realtà una variazione sulla risposta di devdRew è la più accurata - se sostituisci semplicemente '^' con '+' nel tuo codice originale fa la stessa cosa - non hai bisogno dei cast ('int)' come questo accade implicitamente. – DaveRandom

+0

ancora più ordinato! – Matthew

0

È possibile ciclare su un elenco delle variabili e rompere quando hai scoperto un secondo booleano che è vero:

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

come non è più a portata di mano quando si ha più di tre variabili.

+0

Se ci sono più di 3 penso che il metodo 'array_sum' sarebbe più semplice di questo – Matthew

+0

@Matt: Sono d'accordo .. – ezdazuzena

0

x restituirà true se e solo se uno è vero e gli altri sono falsi.

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

Può essere un codice errato, ma funziona.

0

a^b^c^(a & b & c) è l'espressione che stai cercando.

Problemi correlati