マニュアルのHashのページに同様の内容があるのだけど,ちょっと分かりづらかったのでエラーを出す事例とかも含めてまとめ直してみた.
前提:一般的なハッシュの作り方
h = {1=>'a', 2=>'b', 3=>'c'} h = {1, 'a', 2, 'b', 3, 'c'} h = Hash[1=>'a', 2=>'b', 3=>'c'] h = Hash[1, 'a', 2, 'b', 3, 'c'] #=> {1=>"a", 2=>"b", 3=>"c"}
一般的には一番上しか使わないと思うけど,この4通りがどれも同じハッシュを作る.ArrayからHashに変換するときは一番下のパターンを使うので,ここを覚えておいてください.
基本編:[キー, 値, …] の配列からハッシュへ変換する
多重代入の説明時に書いた,’*’を用いた配列の展開を用いてHashを作る.
a = [1,"a", 2,"b", 3,"c"] h = Hash[*a] #=> {1=>"a", 2=>"b", 3=>"c"}
入力側が偶数個でないとエラーになる.
a = [1,"a", 2,"b", 3] h = Hash[*a] #=> ArgumentError: odd number of arguments for Hash
カギカッコでの作成もエラーになる.(多重代入としての処理がされないためだと思う)
a = [1,"a", 2,"b", 3,"c"] h = {*a} #=> SyntaxError: compile error
基本編2:キーと値のペアの配列からハッシュへ
普通は[[キー, 値], [キー, 値], …]っていう2重配列にすると思う.その形式からはflattenを使う.
a = [[1,"a"], [2,"b"], [3,"c"]] h = Hash[*a.flatten] #=> {1=>"a", 2=>"b", 3=>"c"}
ちなみにハッシュを配列に変換するto_aメソッドは2重配列を返す仕様.きわめてややこしいというか,何で非対称な作りになっているんだか理解できない.
h = {1=>"a", 2=>"b", 3=>"c"} a = h.to_a #=> [[1, "a"], [2, "b"], [3, "c"]]
応用編:キーと値の配列のペアからハッシュへ
キーの集合と値の集合が別個の配列になっている場合は,zipやtranposeで結合してから変換する.
keys = [1, 2, 3] vals = ["a", "b", "c"] a = keys.zip(vals) #もしくは a = [keys,vals].transpose h = Hash[*a.flatten] #=> {1=>"a", 2=>"b", 3=>"c"}
keysとvalsの長さが違う場合,transposeはエラーを出す.一方zipは呼び出し元に揃えるので,状況に応じて使い分けると良い.
a1 = [ 1 , 2 , 3] a2 = ['a', 'b'] a1.zip(a2) #=> [[1, "a"], [2, "b"], [3, nil]] a2.zip(a1) #=> [["a", 1], ["b", 2]] [a1,a2].transpose #=> IndexError: element size differs (2 should be 3)