2010-10-04 4 views
5

Ich habe den folgenden Code mit einem kleinen Fehler darin, die case-Anweisung gibt den Wert "other" zurück, obwohl die erste "when" -Anweisung wahr und sollte "Boote" zurückgeben.Kurze Ruby Case-Anweisung mit Include? Funktioniert nicht

Ich habe schon seit langem gesehen, muss etwas klein sein.

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 

Vielen Dank!

+0

Es gibt keine ': cars' Label in Ihrem Hash. Es ist also unmöglich, "Boote" zurückzugeben. – AShelly

Antwort

11

Eine case Anweisung ist in der Regel nur eine Kurzform für eine if Aussage. Sie können neu geschrieben werden als:

Wenn Sie es in dieser Form betrachten, sollten Sie das Problem deutlich sehen; Während include? einen booleschen Wert zurückgibt, vergleichen Sie ihn mit einem ganzzahligen Wert.

+2

Eigentlich 'case' verwendet' === ', nicht' == ', aber in diesem Fall spielt der Unterschied keine Rolle. – sepp2k

+0

@ Sepp2k mein Schlechter, das war es, was ich schreiben wollte. –

7

(Ich werde die Tatsache ignorieren, dass Ihr Hash tatsächlich keine der Schlüssel enthält, nach denen Sie gesucht haben, und so tun, als würden Sie nach Schlüsseln suchen, die sich tatsächlich im Hash befinden. Hoffentlich ist dies die richtige Annahme .)

Sie scheinen zu missverstehen, was eine case Aussage ist. Es testet den Wert des Objekts der case Anweisung, nicht nur eine Reihe von vage verwandt if s. Die when -Klausel sind alle mit === zu dem Objekt der case Aussage verglichen. Wenn Sie also CATEGORY_CLASSES[:boats].include?(category_id) schreiben, bedeutet das entweder if true === category_id oder if false === category_id (seit include? gibt entweder wahr oder falsch zurück).

Was Sie wollen, ist mehr wie CATEGORIES.find {|k,v| v.include? category_id}.first.to_s.

+0

Tatsächlich hat die Ruby-Case-Anweisung zwei Formen, und eine davon ist in der Tat dazu gedacht, eine Reihe veldbezogener ifs zu betreiben. Er wollte wahrscheinlich die andere Fallform verwenden, die Sie erhalten, indem Sie den Fall direkt mit einem Wenn verfolgen. –

39

Sie können Array in erweitern, wenn Anweisung wie folgt:

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

Splat Operator ist hawt, obwohl dies am Ende weniger effizient als eine if-Anweisung sein kann. – MikeJ

+0

Ich bevorzuge diese nette Syntax zur angenommenen Antwort. Auch bezüglich @MikeJ Kommentar wäre ein Benchmark gut. –

Verwandte Themen