リストのリストから,ハッシュのリストを作る
「怠慢はプログラマの美徳」というけれど - kなんとかの日記 を見て,
例えば、スクリプト言語で次のような Hash や Dict を書いたとする。
data = [ {'name'=>'Foo', 'age'=>20, 'email'=>'foo@mail.com'}, {'name'=>'Bar', 'age'=>21, 'email'=>'bar@mail.net'}, {'name'=>'Baz', 'age'=>22, 'email'=>'baz@mail.org'}, ]もしこれをみて何も感じないのであれば、スクリプト言語屋といえど Java 屋を笑うことはできない。本質的でない記述に嫌悪感を感じるセンスがあれば、同じキーが何度も現れていることを「めんどくさい」と感じるはずだ。そして、こんなふうに書けないだろうかと一度は思うはずだ。
data = %h{ ['name', 'age', 'email'], ['Foo', 20, 'foo@mail.com'], ['Bar', 21, 'bar@mail.net'], ['Baz', 22, 'baz@mail.org'], }「怠慢はプログラマの美徳」というけれど - kなんとかの日記
何だかむずむずしてきたので,リストのリストからハッシュのリストを生成するコード片を書いてみた.
#!/usr/local/bin/ruby require 'pp' class Array def to_AoH lambda {|keys, columns| columns.map! {|column| Hash[*keys.zip(column).flatten] } }.call(self.shift, self) end end table = [ [:name, :age, :email], ['Foo', 20, 'foo@mail.com'], ['Bar', 21, 'bar@mail.net'], ['Baz', 22, 'baz@mail.org'], ] pp table.to_AoH
実行結果はこんな感じ.
% ./table2arrayOfHash.rb [{:email=>"foo@mail.com", :name=>"Foo", :age=>20}, {:email=>"bar@mail.net", :name=>"Bar", :age=>21}, {:email=>"baz@mail.org", :name=>"Baz", :age=>22}]
でも,こっちの方が好みかなぁ.
#!/usr/local/bin/ruby require 'pp' class Array def to_AoH(*keys) map {|column| Hash[*keys.zip(column).flatten] } end end aoh = [ ['Foo', 20, 'foo@mail.com'], ['Bar', 21, 'bar@mail.net'], ['Baz', 22, 'baz@mail.org'], ].to_AoH(:name, :age, :email) pp aoh
いや,やはりキーはまず値より先に現れるべきか,と思い直してさらに修正.
#!/usr/local/bin/ruby require 'pp' class Array def to_AoH(*lists) lists.map {|values| Hash[*self.zip(values).flatten]} end end aoh = [:name, :age, :email].to_AoH( ['Foo', 20, 'foo@mail.com'], ['Bar', 21, 'bar@mail.net'], ['Baz', 22, 'baz@mail.org'] ) pp aoh
各リストをそれぞれメソッドの引数に積んでいるので,最後の要素の後ろにカンマ(',')を書けないところが若干気持ち悪いけど,こんなところかなぁ.