ArrayをHash化する方法は有名ですが、キー(添え字)を文字列として合体させる方法を多く見かけます。
しかしキーをSymbolする方法はあまり見かけないので、試してみました。
一般的なユースケース
その1:transposeを使う
keys = ["suzuki", "itou", "yamada"]
values = [87, 76, 69]
key_value_pairs = [keys, values].transpose
h = Hash[*key_value_pairs.flatten]
この実行結果は次の通りです。
key_value_pairs = [keys, values].transpose
=> [["suzuki", 87], ["itou", 76], ["yamada", 69]]
h = Hash[*key_value_pairs.flatten]
=> {"suzuki"=>87, "itou"=>76, "yamada"=>69}
その2:collectとzipを使う
keys = ["suzuki", "itou", "yamada"]
values = [87, 76, 69]
h = Hash[keys.collect.zip(values)]
この実行結果は上記と同様ですが次の通りです。
h = Hash[keys.collect.zip(values)]
=> {"suzuki"=>87, "itou"=>76, "yamada"=>69}
キーをシンボル化してハッシュを作る
その1。違いはkeysの中身だけです。
keys = [:suzuki, :itou, :yamada]
values = [87, 76, 69]
key_value_pairs = [keys, values].transpose
h = Hash[*key_value_pairs.flatten]
この実行結果は次の通りです。
key_value_pairs = [keys, values].transpose
=> [[:suzuki, 87], [:itou, 76], [:yamada, 69]]
h = Hash[*key_value_pairs.flatten]
=> {:suzuki=>87, :itou=>76, :yamada=>69}
その2。keysは文字列ではあるが、それをSymbol化しつつハッシュを作る例は次の通りです。
keys = ["suzuki", "itou", "yamada"]
values = [87, 76, 69]
key_value_pairs = [keys.collect(&:to_sym), values].transpose
h = Hash[*key_value_pairs.flatten]
# zipを用いるとより短く書けます
# keys = ["suzuki", "itou", "yamada"]
# values = [87, 76, 69]
# Hash[keys.collect(&:to_sym).zip(values)]
この実行結果は次の通りです。
key_value_pairs = [keys.collect(&:to_sym), values].transpose
=> [[:suzuki, 87], [:itou, 76], [:yamada, 69]]
h = Hash[*key_value_pairs.flatten]
=> {:suzuki=>87, :itou=>76, :yamada=>69}
同様にCSVデータのような2次元配列に対しても適用できます。
header = [:id, :score]
records = [1, 12], [2, 23], [3, 34]
records.each do |row|
p Hash[*[header, row].transpose.flatten]
# 次のようにも記述できます。
# p [header, row].transpose.to_h
end
この実行結果は次の通りです。スッキリしましたね〜。
{:id=>1, :score=>12}
{:id=>2, :score=>23}
{:id=>3, :score=>34}
なお、Symbolは便利ですがGCまわりの事にもケアしながら利用できると良さそうです!