groovy.util.MapEntry

Hash from two arrays - Rosetta Code から

Groovy
keys = ['a','b','c']
vals = ['aaa', 'bbb', 'ccc']
hash = [:]
keys.eachWithIndex { key, i ->
  hash[key] = vals[i] 
}
Haskell
import Data.Map
 
makeMap ks vs = fromList $ zip ks vs
mymap = makeMap ['a','b','c'] [1,2,3]

Groovy は変数を使っているので、Haskell のやり方を Groovy で実装することにする。


Java では Map.Entry は public だが各 Map の Entry の実装クラスは public ではない。
Groovy では Map に entry のみを追加する API があり、Map.Entry が必要なときは groovy.util.MapEntry が使える。

assert hash == [:].putAll([keys, vals].transpose().collect { k, v -> new MapEntry(k,v) })
assert hash == [:] + [keys, vals].transpose().collect { k, v -> new MapEntry(k,v) }
assert hash == [:] + [keys, vals].transpose().collect { it as MapEntry }
assert hash == [:] + [keys, vals].transpose()*.asType(MapEntry)
  • putAll から + に変更してみる
  • リストは key, value のペアでコンストラクタ引数と同じ順序なので as で強制型変換できる
  • クロージャ内の処理が特にないので展開ドット演算子に変更してみる

2011-05-27 追記

Groovy 1.8 で List#toSpreadMap が追加されていた。
SpreadMap を使っている人がいるんだろうか?

assert hash == [keys, vals].transpose().flatten().toSpreadMap().@mapData

2011-05-31 追記

Groovy 1.7.9 で追加された Collection#collectEntries が Hash from two arrays のための API のようだ。

assert hash == [keys, vals].transpose().collectEntries { it }