2011-12-16 7 views
1

を美化だから私はこのコードを持っている:ルビー、値のバケットは、コード

def self.age_to_bucket(age) 
    age = age.to_i 

    if age >= 0 && age <= 12 
    1 
    elsif age >= 13 && age <= 17 
    2 
    elsif age >= 18 && age <= 24 
    3 
    elsif age >= 25 && age <= 29 
    4 
    elsif age >= 30 && age <= 34 
    5 
    elsif age >= 35 && age <= 39 
    6 
    elsif age >= 40 && age <= 49 
    7 
    elsif age >= 50 && age <= 64 
    8 
    elsif age >= 65 
    9 
    else 
    0 
    end 
end 

はどうやってその読みやすさを失うことなく、このコードを向上させることができますか?

私はこのように、範囲を#in?を使用することができます知っている:

if age.in? (0..12) 

が、#in? activesupportの中にある、と私はむしろ、複数の独立した方法を使用すると思います。

+0

これは好きですか、あまりにも抽象的ですか? '[0、12、13、17、...]。find_interval(15)#=> 2'。実装がかなり簡単です(効率的に行うのが少し難しい)。 – tokland

+0

私は '{0、13、18、...]。find_interval(15)' – tokland

+0

私は自分で何も実装していません。 –

答えて

6

一つの方法は、他の方法、条件で冗長& &を排除するであろう場合

result = case age 
when 0..12 then 1 
when 13..17 then 2 
when 18..24 then 3 
when 25..29 then 4 
-------- so on 
else 0 
end 

を使用することです。

if age < 0 
    0 
elsif age < 13 
    1 
elsif age < 18 
    2 
elsif age < 25 
    3 
elsif age < 30 
    4 
elsif age < 35 
    5 
elsif age < 40 
    6 
elsif age < 50 
    7 
elsif age < 65 
    8 
else 
    9 

UPD:このトピックのすべてのアドバイスの結果として、コードの最終バージョン:https://gist.github.com/1485288

+0

'case'のケースで' age> 65'をどう表現しますか? –

+1

'(65..Float :: INFINITY)'です。 1.8のためにあなた自身の無限大を作る: '無限大= 1.0/0' – tokland

+0

現在のバージョンはこのようになります:https://gist.github.com/1485288 もっと良い、imho。みんなありがとう。 –

1

あなたはvanilla Rubyある(0..12).include? ageからif age.in? (0..12)を、書き換えることができます。ちょうど楽しみのため

+0

ええ、それは悪く見えます:-) –

0
irb(main):010:0> a = {1 => 0..12, 2 => 13..17} # insert other values here 
=> {1=>0..12, 2=>13..17} 
irb(main):011:0> age = 16 
=> 16 
irb(main):012:0> a.keys.find {|k| a[k].include?(age) } 
=> 2 
+0

「elsif age> = 65」の場合、この範囲をどのようにしますか? – megas

+0

nilをチェックし、ifテストを追加します。 – Geo

2
def self.age_to_bucket age 
    case age=age.to_i 
    when 0..12 then 1 
    when 13..17 then 2 
    when 18..24 then 3 
    when 25..29 then 4 
    when 30..34 then 5 
    when 35..39 then 6 
    when 40..49 then 7 
    when 50..64 then 8 
    else age >= 65 ? 9 : 0 
    end 
end 
1

(これは効率的な方法ではありませんが、小さな配列のためだけで結構です):間隔がダイナミックだった場合は、実装する必要があるだろうということ

ranges = [0, 13, 18, 25, 30, 35, 40, 50, 65, Float::INFINITY].each_cons(2).map { |a, b| (a..b) } 
n = ranges.map.with_index { |range, idx| idx if range.include?(15) }.compact.first + 1 
#=> 2 

注意それは同様の方法で。

+0

これは "スマート"で隠蔽的なコードです:-) –

+1

@Sergei:静的なケースは「クリア」ではありませんが、プログラマチックには同様のことをする必要があります。プログラミングは抽象化を書くことであり、抽象化を恐れるものではありません。 'map.with_index'は有効なRuby 1.9です。 – tokland

+0

ええ、私は静的な間隔の私の場合、これはあまりにも複雑な解決策であることを意味します。動的な間隔は別の話です。 –