27677


コード自体はかけたのですが、もう少し上手くかけないかと思い質問致します。

[code]

    ﻿﻿a = [[2014, 3], [2014, 5], [2015, 4], [2016, 2], [2016, 8]]
    
[/code]

という配列から、配列の初めの要素に入っている年号をキーにした

[code]

    {2014 => [3, 5],
     2015 => [4],
     2016 => [2, 8]}
    
[/code]

という`Hash`を生成したく

[code]

    a.group_by(&:first).map{|k, v| [k, v.map(&:last)]}.to_h
    
[/code]

と書いたのですがかなりわかりにくい気がするので

[code]

    h = {}
    a.each do |k, v|
      h[k] ||= [] 
      h[k] << v
    end
    h
    
[/code]

としました。できればもう少しすっきり書きたいのですがもっとシンプルな書き方はありますか？


CC BY-SA 3.0
2016-07-16T23:27:19.817
27676
2016-07-17T23:59:42.960
3271
question
ruby
2次元配列の特定の値をキーにしたHashを生成する方法


私もいつも悩みます。  
その中でもやっているのは、デフォルト値を使うことで、key の判定を省略する方法です。

[code]

    h = Hash.new { |h, k| h[k] = [] }
    a.each do |k, v|
      h[k] << v
    end
    h
    
[/code]

またこちらの記事 <http://qiita.com/cuzic/items/a265f140fdff289d5c07#objecttap>
を読んでから、tap を使うことも多いです。

[code]

    years_month_lists = {}.tap do |h|
      a.each do |k, v|
        h[k] ||= []
        h[k] << v
      end  
    end
    
[/code]


CC BY-SA 3.0
2016-07-17T00:07:03.593
27677
2016-07-17T00:07:03.593
7471
27676
answer


`inject` を使うのはどうでしょうか。

[code]

    a.inject(Hash.new([])){|h, (k, v)| h[k] += [v]; h}
    
[/code]


CC BY-SA 3.0
2016-07-17T03:32:10.660
27678
2016-07-17T23:59:42.960
2016-07-17T23:59:42.960
27676
answer

[code]

    h = a.each_with_object({}) do |(k, v), res|
      res[k] ||= []
      res[k] << v
    end
    
    p h
    
[/code]


CC BY-SA 3.0
2016-07-17T11:01:02.040
27682
2016-07-17T11:01:02.040
9008
27676
answer


あくまで、`a`を破壊してもいいという前提ですが・・・

[code]

    a.group_by(&:shift).each_value(&:flatten!)
    
[/code]


CC BY-SA 3.0
2016-07-17T13:48:54.337
27688
2016-07-17T13:48:54.337
9608
27676
answer