Ruby 練習問題集 ループ処理 (2)

ループ処理 (2) - Ruby 練習問題集 - Ruby on Rails with OIAX

今、任意の個数のメールアドレスがあり、ドメイン別にメールアドレスが何個あるかを調べたい。

メールアドレスの配列 ary を引数として取り、ハッシュオブジェクトを返すメソッド foo を作りなさい。

ただし、そのハッシュオブジェクトは以下の条件を満たすこと。

各キーはメールアドレスのドメイン部分(@より後ろの部分)である。
各値は、そのドメイン部分がキーと合致するメールアドレスの個数である。
例えば、次のようなメールアドレスの集合を考える。

john@sample.com
taro@sample.jp
nancy@sample.com
jiro@sample.jp
hermes@oiax.jp
saburo@sample.jp
これらのメールアドレスを要素として持つ配列を作って foo に渡すと、次のようなハッシュオブジェクトが返ることになる。

{
'sample.com' => 2,
'sample.jp' => 3,
'oiax.jp' => 1
}

まぁやってみた

準備

mails=%w(john@sample.com taro@sample.jp nancy@sample.com jiro@sample.jp hermes@oiax.jp saburo@sample.jp)
def foo(ary)
  h = {}
  ary.each do |x|
    domain = x.split("@")[1]
    if h.key?(domain)
      h[domain] += 1
    else
      h[domain] = 1
    end
  end
  h
end

mails=%W(john@sample.com taro@sample.jp nancy@sample.com jiro@sample.jp hermes@oiax.jp saburo@sample.jp)
foo(mails)
=> {"sample.jp"=>3, "oiax.jp"=>1, "sample.com"=>2}

回答を見て納得

ああ、そうか。こういう時こそinjectだった。

= も正規表現も見やすい。
def foo(ary)
  ary.inject({}) do |hsh, email|
    domain = email.match(/@/).post_match
    hsh[domain] ||= 0
    hsh[domain] += 1
    hsh
  end
end

foo(mails)
=> {"sample.jp"=>3, "oiax.jp"=>1, "sample.com"=>2}