Ruby の Hash リテラルでキーが重複している場合の奇妙な動作

最近こういう動作を見つけたので覚書。

Hash リテラルでキーが重複しているとどうなるのか

Hash リテラルで Hash を定義した場合、キーの順番は『記述した順番』になります。

# ここで定義した順番になる
hash = { age: 14, name: "homu" }
pp hash
# => {:age=>14, :name=>"homu"}

hash = { name: "homu", age: 14 }
pp hash
# => {:name=>"homu", :age=>14}

では、この Hash リテラルでキーが重複しているとどうなるのかというと次のようになります。

# age が重複している場合
hash = { id: 1, age: 14, name: "homu", age: 20, age: 10 }
# キーの順番は age が先にくるが、値は最後に定義した値になる
pp hash
# => {:id=>1, :age=>10, :name=>"homu"}

こんな感じで

  • キーの位置は『最初に定義された位置』
  • キーの値は『最後に定義された値』

という挙動になります。
キーの位置と値が異なるのでちょっと混乱しますね。
このような書き方をすると警告もでますし、基本的に Hash リテラルではキーを重複して書かないようにしましょう。

# warning: key :age is duplicated and overwritten on line 2
hash = { id: 1, age: 14, name: "homu", age: 20, age: 10 }

関連