2010-10-04 10 views
5

Ho il seguente codice con un piccolo bug in esso, l'istruzione case restituisce il valore "altro" anche se la prima istruzione "when" è vera e deve restituire "boats".Dichiarazione caso breve rubino usando include? Non funziona

Sono stato a guardare questo per secoli, deve essere qualcosa di piccolo.

CATEGORIES = {:boats => [1, 2, 3, 4, 5, 6], 
       :houses => [7, 8, 9, 10], 
       :other => [11,12,13,14,15,16] 
      } 

category_id = 1 

category = case category_id 
    when CATEGORY_CLASSES[:boats].include?(category_id); "boats" 
    when CATEGORY_CLASSES[:houses].include?(category_id); "houses" 
    else "other" 
end 

Grazie!

+0

Non c'è ': etichetta cars' nel vostro hash. Quindi è impossibile restituire "barche" – AShelly

risposta

11

Un'istruzione case è in genere solo una scorciatoia per un'istruzione if. Le vostre riscritte possono essere:

if CATEGORY_CLASSES[:boats].include?(category_id) === category_id 
    category = "boats" 
elsif CATEGORY_CLASSES[:houses].include?(category_id) === category_id 
    category = "houses" 
else 
    category = "other" 
end 

Quando lo guardate in questo modulo, dovreste vedere chiaramente il problema; mentre include? restituisce un valore booleano, lo stai confrontando con un valore intero.

+2

In realtà 'case' usa' === ', non' == ', ma in questo caso la differenza non ha importanza. – sepp2k

+0

@ sepp2k mio male, questo è quello che intendevo scrivere. –

7

(Ho intenzione di ignorare il fatto che il tuo hash in realtà non contiene nessuno dei tasti che stavi controllando e fai finta di controllare le chiavi che sono effettivamente nell'hash ... spero che questa sia la giusta ipotesi .)

Ti sembra di fraintendere cosa sia un'istruzione case. Sta testando il valore dell'oggetto della dichiarazione case, non semplicemente eseguendo un gruppo di nomi vagamente correlati, if. I valori di when -claus sono tutti confrontati con === sull'oggetto dell'istruzione case. Quindi se scrivi CATEGORY_CLASSES[:boats].include?(category_id), allora significa if true === category_id o if false === category_id (dal include? restituisce vero o falso).

Quello che vuoi è più simile a CATEGORIES.find {|k,v| v.include? category_id}.first.to_s.

+0

In realtà l'affermazione del caso Ruby ha due forme, e una delle è in realtà destinata a gestire un gruppo di ifs vagamente correlati. Probabilmente intendeva usare l'altro caso, che si ottiene seguendo il caso direttamente con un quando. –

39

È possibile espandere matrice in quando economico come segue:

category = case category_id 
    when *CATEGORY_CLASSES[:boats]; "boats" 
    when *CATEGORY_CLASSES[:houses]; "houses" 
    else "other" 
end 
+0

L'operatore di Splat è falso, sebbene questo possa risultare meno efficiente di un'istruzione if. – MikeJ

+0

Preferisco questa bella sintassi alla risposta accettata. Anche per quanto riguarda @MikeJ commentare un benchmark sarebbe bello. –