「hashMap」メソッド
jijixi's diary - 関数型脳になると、ちょっとイラっとする Ruby の要素 , ActiveSupport::OrderedHash に絶望したで、
例えば、あるハッシュをいじって別のハッシュを作りたいときがある。 関数型脳なんだから、当然のように元のハッシュを書き換えるんじゃなく、新たなハッシュを作りたい。
ここで、手続き型脳で考えた場合、話は簡単だ。irb(main):001:0> a = { :hoge => 1, :fuga => 2, :piyo => 3 } => {:hoge=>1, :fuga=>2, :piyo=>3}irb(main):002:0> b = {} => {} irb(main):003:0> a.each do |k,v| irb(main):004:1* b[k] = v + 1 irb(main):005:1> end => {:hoge=>1, :fuga=>2, :piyo=>3}こう書けば良い。 でも、関数型脳で考えると、こういうシチュエーションはどうしても map を使いたくなる。
から始まって、つらつらとRubyじゃ出来ないよー、と嘆いてるを見て、
なんかこの「ハッシュをかえすハッシュ.map」て、欲しかったら動的メソッド足せばええやん、とか思った。適当な名前で…「hashMap()」?
とかtwitterで言ってしまったので書いてみました。
要は、
assert [a:1, b:2, c:3].hashMap{it*2} == [a:2, b:4, c:6]
が出来ればうれしいんでしょ?ということで出来るようにしました。
LinkedHashMap.metaClass.hashMap = {clos-> def res = [:] delegate.each {key, value->res[key] = clos(value)} return res } assert [a:1, b:2, c:3].hashMap{it*2} == [a:2, b:4, c:6]
…中身はまんまやん!
もうちょっとかっこ良く書きたいなぁ…ということで、第二弾。
LinkedHashMap.metaClass.hashMap = {clos-> delegate.collect{[(it.key):clos(it.value)]}.sum() } assert [a:1, b:2, c:3].hashMap{it*2} == [a:2, b:4, c:6]
いちおう関数型ぽい?
…しかし重そう、と思ってちょっと計ってみたら、2.4GHz Core 2 Duoの乗ったMac上のJava6:groovy1.6で10000件のMapのhashMap{it*2}に4秒かかりましたw