2008-10-22 13 views
8

Czytałem o wyrażeniach w stylu warunkowym w ruby. Jednak natknąłem się na jedną z nich, której nie mogłem zrozumieć, aby zdefiniować klasyczny problem FizzBuzz. Rozumiem problem z FizzBuzz, a nawet napisałem własne, zanim znalazłem następujące szybkie rozwiązanie wykorzystujące operatora trójskładnikowego. Jeśli ktoś może mi wyjaśnić, jak to działa, aby zaspokoić łańcuch problem FizzBuzz byłoby bardzo mile widziane :)FizzBuzz za pomocą trójskładnikowego operatora warunkowego

for i in 0...100 
    puts i%3==0 ? i%5==0 ? "FizzBuzz" : "Buzz" : i%5==0 ? "Fizz" : i 
end 

Odpowiedz

16

Niektóre nawiasy może pomóc:

puts (i%3 == 0) ? ((i%5 == 0) ? "FizzBuzz" : "Buzz") : ((i%5 == 0) ? "Fizz" : i) 

Więc jeśli jest podzielna przez 3 , następnie sprawdza, czy element i jest podzielny przez 5. Jeśli tak, wypisuje "FizzBuzz", inaczej "Buzz". Jeśli nie podzielę się przez trzy, to sprawdza podzielność przez 5 ponownie i drukuje "Fizz", jeśli tak, inaczej tylko ja.

+0

Dzięki bardzo - nawias a wyjaśnienie rozwiązało ten problem – Damian

1

przepływ jest:

if (i%3 == 0) {    // multiple of 3 
    if (i%5 == 0) {   // multiple of 3 and 5 
     puts "FizzBuzz" 
    } else {     // not multiple of 5, only of 3 
     puts "Buzz" 
    } 
} else (     // not multiple of 3 
    if (i%5 == 0) {   // multiple of 5, not of 3 
     puts "Fizz" 
    } else {     // multiple of neither 5 nor 3 
     puts i 
    } 
} 
3

Trójskładnikowy jest podstawowym jeżeli-to struktura.

Powyższy odpowiada ...

if i%3 ==0 
    if i%5 == 0 
     "FizzBuzz" 
    else 
     "Buzz" 
else 
    if i%5 == 0 
     "Fizz" 
    else 
     i 

Lub przy niektórych parens ...

puts i%3==0 ? (i%5==0 ? "FizzBuzz" : "Buzz") : (i%5==0 ? "Fizz" : i) 
+1

czyta ten kod bez nawiasów robi mi drgać . – nickf

+0

Przepraszamy. Po prostu byłem leniwy. –

+0

Udawaj, że jest to pseudokod. ;-) – Wickethewok

11

Oto opis problemu FizzBuzz jak stwierdzono w tym Jeff Atwood article.

Napisz program, który drukuje numery od 1 do 100. Ale dla wielokrotności trzech print „Fizz” zamiast numeru i dla wielokrotności pięciu print „Buzz”. W przypadku numerów , które są wielokrotnościami obu znaków, trzy i pięć wydrukują "FizzBuzz".

A ternary operator jest skrótem dla instrukcji if-else. Ogólny format:

 
cond ? evaluate_if_cond_is_true : evaluate_if_cond_is_false 

Więc jeśli piszę:

int isEven = (i % 2 == 0) ? 1 : 0; 

jest równoznaczne z następującym kodem:

if (i % 2 == 0) { 
    isEven = 1; 
} else { 
    isEven = 0; 
} 

Gdzie dyr jest i % 2 == 0, evaluate_if_cond_is_true jest 1 i evaluate_if_cond_is_false jest 0 .

Fajną cechą operatorów trójskładnikowych jest to, że można je łączyć. Oznacza to, że instrukcja do wykonania, gdy dowolny warunek zostanie zwrócony do wartości true lub false, może być kolejnym operatorem potrójnym.

Niech umieścić całą sytuację w bardziej czytelny sposób:

i%3==0 ? 
    i%5==0 ? 
     "FizzBuzz" 
     : "Buzz" 
    : i%5==0 ? 
     "Fizz" 
     : i 

i mapowanie to do if-else jest łatwe z zasadami wyjaśniono powyżej:

if (i%3==0) { 
    if (i%5==0) { 
     "FizzBuzz" 
    } else { 
     "Buzz" 
    } 
} else { 
    if (i%5==0) { 
     "Fizz" 
    } else { 
     i 
    } 
} 

To nie jest poprawny kod ale ponieważ wynik potrójnego operatora jest podkreślony w wyrażeniu wyniku, jest używany jako dane wejściowe dla polecenia puts.

7

Dla zabawy, tu jest inny sposób:

puts (1..100).map {|i| (fb = [["Fizz"][i%3],["Buzz"][i%5]].compact.join).empty? ? i : fb} 

I jeszcze:

(1..100).zip([nil,nil,"Fizz"]*34,[nil,nil,nil,nil,"Buzz"]*20).map {|a,b,c| b || c ? [b,c].join : a} 
+1

To jest złe. Specyfikacja mówi, że powinieneś wydrukować tylko ten numer, jeśli nie drukujesz fizz lub buzz. – mxcl

+0

Ah, to prawda. –

Powiązane problemy