2012-01-30 18 views
8

Jeśli mam następujące wartości logicznychUpewnij się, że dokładnie jedna boolean danej listy jest prawdziwa?

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

Co mogę napisać kod, aby upewnić się, że dokładnie jedna jest prawdziwa?

Próbowałem to:

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

Problemem jest to, że ze wszystkich trzech stałe ustawiona na true następnie $x jest true.

+0

możesz umieścić całą kombinację używając warunku OR '(WCZEŚNIEJ = true AND TODAY = false I JUTRA = false) lub (YESTERDAY = false AND TODAY = true AND TOMORROW = false) lub (YESTERDAY = false AND TODAY = false AND TOMORROW = true) ' –

+0

On musi mieć pewność, że prawda jest excalty ONE, a nie CO NAJMNIEJ. – devdRew

Odpowiedz

8

$x = ((int) self::YESTERDAY) + ((int) self::TODAY) + ((int) self::TOMORROW); Następnie jeśli $x === 1; Masz to, czego potrzebujesz.

edycja:

Nawet bez typu rzuca (int), to działa dobrze, dzięki @DaveRandom, więc:

if (self::YESTERDAY + self::TODAY + self::TOMORROW == 1) {}, jak dla mnie.

+0

Zastanowiłem się nad tym, ale byłoby miło uniknąć tego dodatkowego przetwarzania, czy jest jakiś sposób na zrobienie tego? – Matthew

+0

+1 to - wydaje się po przetestowaniu, że nie potrzebujesz nawet rzutowania '(int)', dzieje się to niejawnie. – DaveRandom

+1

Jest to znacznie bardziej przejrzyste niż jakiekolwiek inne rozwią[email protected] był prawie poprawny w użyciu operatora XOR (^), ale niestety 'true^true^true' zwróci wartość 'true', ponieważ PHP interpretuje ją jako' (true^true)^true', ie 'false^true ' – WildlyInaccurate

0

tylko jako alternatywa dla devdRew za odpowiedź

$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

neatest sposób mogę myśleć jest array_sum():

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

EDIT Faktycznie, wszystko co musisz zrobić, to wymienić ^ z + w pierwotnej próbie, i osiąga to samo:

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

Powoduje to zmianę $x na liczbę wartości TRUE. Tak dla logicznej użytku wyjściowych:

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

jest całkiem schludny! – Matthew

+0

W rzeczywistości odmiana odpowiedzi devdRew jest najmądrzejsza - jeśli po prostu zamienisz '^' na '+' w oryginalnym kodzie, robi to samo - nie potrzebujesz "(int)", ponieważ dzieje się to niejawnie. – DaveRandom

+0

to jeszcze więcej! – Matthew

0

można pętli nad listą zmiennych i złamać, kiedy znaleźli drugą wartość logiczną, która jest prawdziwe:

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

Jak to jest bardziej przydatny, gdy masz więcej niż trzy zmienne.

+0

Jeśli jest więcej niż 3, myślę, że metoda 'array_sum' byłaby prostsza niż ta – Matthew

+0

@Matt: Zgadzam się .. – ezdazuzena

0

x zwróci wartość true wtedy i tylko wtedy, gdy jedna jest prawdą, a inne są fałszywe.

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

Może to być zły kod, ale działa.

0

a^b^c^(a & b & c) to ekspresja, której szukasz.

Powiązane problemy