大ちゃんの駆け出し技術ブログ

RUNTEQ受講生のかわいいといわれるアウトプットブログ

【無職に転生 ~ 就職するまで毎日ブログ出す_12】【Ruby】ハッシュの使い方②

はじめに

こんにちは、大ちゃんの駆け出し技術ブログです。

タイトルにあるとおり【無職に転生 ~ 就職するまで毎日ブログ出す】というチャレンジをしています!!!!昨日までは就活するまで本気出すでしたが、これだとまるで就活後は頑張らないのかと思われてしまいそうで、、、大人気アニメのタイトルのまるパクリチャレンジです。

https://i.gyazo.com/3a02b7aae4e5e538130d4bb199b55dc7.png

RailsやらRubyやらSQLやらその他Webの知識やらが色々と抜け落ちているのを感じており、知識の定着のためにもアウトプットする機会を増やすためです。加えて、退職して文字通り無職に転生しましてプロニートになり、毎日時間に余裕ができたので引き締めるためにも毎日投稿を思い至りました!

【投稿内容】

  • SQLの難しい処理 (副問合せ、JOINとか複雑な処理が書けない)
  • Rails全般 (純粋に必要な知識が多すぎる、網羅的な理解が足りない)
  • Rubyのあまり使わないメソッドや記述方法 (あまり重要ではないけど特に)
  • Web知識全般 (クッキーやら、セッションやらなんとなくで理解しているものの自分の言葉で説明できない)
  • 書籍 (スタートアップ企業に勤めるので、自分が会社に与える影響やパフォーマンスを高めるためビジネス書を読んでいきます。)

本日やること

本日もハッシュについて復習していきます。昨日もハッシュについて学びましたがさらに深めるべく復習していきます。

【無職に転生 ~ 就職するまで毎日ブログ出す_11】【Ruby】ハッシュの使い方 - 大ちゃんの駆け出し技術ブログ

いつも大変お世話になっているチェリー本の第5章にかなり具体的に書かれているので、それを参考にしつつ他の記事も引用して開発できたらなと思います。

プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで (Software Design plusシリーズ)


追加でハッシュのメソッド

昨日は少しだけ紹介できなかったので再度使えそうなメソッドを紹介していきます。再掲しますがハッシュのメソッドは非常に多いです。ですが、多くの挙動はArrayと同じですので、覚えてしまえばどちらにも使えてしまうので一石二鳥です!

https://i.gyazo.com/68568bf926eff0b66d559134fcdb8f15.png

fetch

キーを指定してそれに対応するバリューを取得します。

hash = {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs}
hash.fetch(:ruby)
=> :rails

digメソッド に続きまた取得のメソッドですね。digメソッドと違う点として、キーが見つからない場合にエラーになります。

hash.fetch(:java)
# KeyError (key not found: :java)

KeyErrorと指定したキーが見つからないというエラーになります。これでは本来の【ハッシュ[キー]】との差別化があまりないように見えますが、実はfetchメソッドは第二引数を指定することができます。この第二引数はKeyErrorが起こった場合、つまり指定したキーが見つからなかった場合、第二引数で指定した値が返り値として返却されます。つまりKeyErrorを回避することができます。

hash.fetch(:ruby, "KeyErrorを回避")
=> :rails
hash.fetch(:java, "KeyErrorを回避")
=> "KeyErrorを回避"

階層が深いキーに対しては使うことができないようです。なぜなら引数が二つまでしか定義できないためです。第二引数はかならずKeyErrorが起きたときの返り値となるため、階層が深いキーの取得にはあまり向かないかなと思います。

fetch(key, default = nil)
hash = {frameworks: {ruby: :rails, python: :Django, JS: :Vuejs}}
=> {:frameworks=>{:ruby=>:rails, :python=>:Django, :JS=>:Vuejs}}
hash.fetch(:frameworks,:ruby)
=> {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs}

merge

レシーバーと引数のハッシュを結合させて新しいハッシュを返します。

another_hash = {java: :Spring_Framework}
=> {:java=>:Spring_Framework}
hash.merge(another_hash)
=> {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs, :java=>:Spring_Framework}

これはハッシュの追加、更新とほとんど同様の挙動ですが、引数のハッシュによって更新と追加を同時に行えます。というのもメソッドの挙動としてはレシーバーであるハッシュに対して引数にレシーバーにはない新しいキーがあればそれを追加し、レシーバーに既にある既存のキーがー引数で渡されればそれを更新します。

another_hash = {java: :Spring_Framework, JS: :React}
=> {:java=>:Spring_Framework, :JS=>:React}
hash.merge(another_hash)
=> {:ruby=>:rails, :python=>:Django, :JS=>:React, :java=>:Spring_Framework}

上記では既にキーがある:JSと同じキーば引数にも含まれており、そのバリューは違う値である:Reactです。よってもとのレシーバーの:Vuejsが更新され:Reactに変わっています。

mergeメソッドはrailsではよくストロングパラメータの定義箇所で使われています。

params.require(:モデル名).permit(:キー名, :キー名,・・・).merge(user_id: current_user.id)

invert

invertメソッドはキーと値を入れ替えたハッシュを返します。

hash = {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs}
hash.invert
=> {:rails=>:ruby, :Django=>:python, :Vuejs=>:JS}

ハッシュの中身を大きく操作するメソッドなので使い所は分かりませんが、便利なメソッドであることは間違い無いです。ちなみに下記のようにバリューが同じハッシュがある場合、最後の要素の組み合わせが返却されます。

hash = {ruby: :rails, python: :Django, JS: :Vuejs, Javascript: :Vuejs}
=> {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs, :Javascript=>:Vuejs}
hash.invert
=> {:rails=>:ruby, :Django=>:python, :Vuejs=>:Javascript}

元のハッシュより短くなってしまいますが同じキーは二つ存在することはできないためです。よって最後に評価される1番後ろの組み合わせだけが残ります。

transform_keys

すべてのキーに対してブロックを呼び出した結果で置き換えたハッシュを返します。値は変化しません。

Hash#transform_keys (Ruby 3.0.0 リファレンスマニュアル)

キーに対して評価しそれを反映させた新しいハッシュを返します。

hash.transform_keys {|k| k.upcase}
=> {:RUBY=>:rails, :PYTHON=>:Django, :JS=>:Vuejs, :JAVASCRIPT=>:Vuejs}

transform_values

すべての値に対してブロックを呼び出した結果で置き換えたハッシュを返します。キーは変化しません。

Hash#transform_values (Ruby 3.0.0 リファレンスマニュアル)

transform_keysとは逆のことをします。

hash.transform_values {|v| v.upcase}
=> {:ruby=>:RAILS, :python=>:DJANGO, :JS=>:VUEJS, :Javascript=>:VUEJS}

ハッシュ < = > 配列

ハッシュから配列に変換する方法、その逆である配列からハッシュに変換する方法は簡単です。to_ato_hメソッドを使います。

hash.to_a
=> [[:ruby, :rails], [:python, :Django], [:JS, :Vuejs], [:Javascript, :Vuejs]]
hash.to_a.to_h
=> {:ruby=>:rails, :python=>:Django, :JS=>:Vuejs, :Javascript=>:Vuejs}

ただし、ハッシュから配列にした時にきれいな配列として返るわけではなく階層の配列として返却されています。そのため、Arrayクラスのメソッドであるflattenメソッドも同時に使うパターンもありそうです。

hash.to_a.flatten
=> [:ruby, :rails, :python, :Django, :JS, :Vuejs, :Javascript, :Vuejs]

終わりに

次の記事ではJQueryについて書こうと思います。JQueryを全然勉強したことがなくて今チーム開発で使っていて全く読めずめちゃくちゃ困っています。

参考記事

ハッシュの便利メソッドあれこれ - Qiita

要素の追加と値の変更

ストロングパラメーター