Her 'when' bloğunda birden fazla değere sahip vaka bildirimi


314

Aradığım şeyi açıklayabilmemin en iyi yolu, şu ana kadar denediğim başarısız kodu göstermektir:

case car
  when ['honda', 'acura'].include?(car)
    # code
  when 'toyota' || 'lexus'
    # code
end

whenYaklaşık 50 farklı olası değerle tetiklenmesi gereken yaklaşık 4 veya 5 farklı durumum var car. Bunu casebloklarla yapmanın bir yolu var mı yoksa büyük bir ifblok mu denemeliyim ?

Yanıtlar:


669

Bir de caseaçıklamada, bir ,eşdeğerdir ||bir in ififadesi.

case car
   when 'toyota', 'lexus'
      # code
end

Ruby vaka bildirimi ile yapabileceğiniz diğer bazı şeyler


1
Bu bağlantının Ruby'deki vaka ifadelerinin daha iyi bir özeti vardır (ve regexp ve splat sözdiziminin örneklerini de içerir).
rsenna

Ben neden bilmiyorum, ama bu garip durum olur: Bu yazarken: when "toyota", "lexus"ben alıyorum: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Ancak, bunu yazdığımda: when "toyota","lexus"işe yarıyor. Tek fark virgülden sonraki boşluktur.
Furkan Ayhan

@FurkanAyhan Bu çok garip. Devam ettim ve sadece emin olmak için kodu test ettim ve işe yarıyor. Benim tahminim, kodunuzda böyle bir hata yapan başka bir şey var. Bir yerde bir tel ya da onun gibi bir ipi kapatmayı unutmak mümkün mü?
Charles Caldwell

1
Peki, bu işe yarıyor, ama programcı kolaylığı üzerinde yakut odaklanma olarak, niçin niçin standardı desteklemiyor acaba || yada yada'? Bu biraz kafa karıştırıcı
Zia Ul Rehman Mughal

2
Ruby desteklemiyor orveya ||burada desteklenmiyor çünkü whentek bir tanımlayıcı değil, sağında virgülle ayrılmış bir dizi ifade alıyor. Eğer olsaydı Bu nedenle, when a or bbu bunun eşdeğeri olarak alınacak olup olmadığı net değil when a, bveya when (a or b)ifadeyi değerlendirir ikinci olan, a or bne zaman atmadan önce ilk. Dile göre davranışı bağlama göre değiştiren belirteçlere sahip olmak daha şaşırtıcı ve daha az kolaydır ve daha sonra bir orzamanın sağ tarafında gerçek bir ifade kullanamazsınız .
Taywee

99

Ruby'nin "uyarısı" veya düzleştirme sözdiziminden yararlanabilirsiniz.

Bu, aşırı büyümüş whenhükümler yapar - doğru anlarsam dal başına test etmek için yaklaşık 10 değeriniz var - bence biraz daha okunabilir. Ayrıca, çalışma zamanında sınamak için değerleri değiştirebilirsiniz. Örneğin:

honda  = ['honda', 'acura', 'civic', 'element', 'fit', ...]
toyota = ['toyota', 'lexus', 'tercel', 'rx', 'yaris', ...]
...

if include_concept_cars
  honda += ['ev-ster', 'concept c', 'concept s', ...]
  ...
end

case car
when *toyota
  # Do something for Toyota cars
when *honda
  # Do something for Honda cars
...
end

Diğer bir genel yaklaşım, her bir değerinin anahtarları carve yürütmek istediğiniz kodu çevreleyen bazı çağrılabilir nesneler olan bir karma tablosu dağıtım tablosu olarak kullanmaktır .


Kullanmayı bitirdiğim halde, birinin onay işaretini almaktan kötü hissediyorum: D
Nick

Uzun whenhatlar için mükemmel çözüm . Paylaşım için teşekkürler.
Pistos

0

Mantığınızı veriye koymanın bir başka güzel yolu da şudur:

# Initialization.
CAR_TYPES = {
  foo_type: ['honda', 'acura', 'mercedes'],
  bar_type: ['toyota', 'lexus']
  # More...
}
@type_for_name = {}
CAR_TYPES.each { |type, names| names.each { |name| @type_for_name[type] = name } }

case @type_for_name[car]
when :foo_type
  # do foo things
when :bar_type
  # do bar things
end

Kaba olmak istemiyorum, ama aşağı indirdim çünkü bu hem zaman hem de mekanda daha az verimli. Ayrıca diğer iki cevaptan daha karmaşık ve daha az okunabilir. Bu yöntemi kullanmanın yararı nedir?
Nick

Tüm sınıflandırmanızı tek bir nesneye koyar. Artık bu nesneyle serileştirmek ve mantığınızı açıklamak için başka birine gönderebilir veya bir veritabanında saklayıp insanların düzenlemesine izin verebilirsiniz. (Yeni araba modelleri çıktığında mantık çok yakında değişecek, değil mi?) "Masaya dayalı" görünebilirsiniz.
Hew Wolff

YAGNI ("İhtiyacınız olmayacak") burada geçerli olabilir. Tasarım, gelecekte var olabilecek ancak henüz var olmayan bir senaryo için zaman / alan verimliliğini ve okunabilirliğini feda eder. Maliyet şimdi ödenir, ancak ödül asla alınamaz.
Nick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.