[解決済み] Rubyで記号をハッシュキーとして使う理由とは?
質問
Rubyのハッシュのキーとしてシンボルを使うことがよくあります。
文字列を使うことの利点は何ですか?
例
hash[:name]
vs.
hash['name']
解決方法は?
TL;DR。
シンボルを使用すると、比較の際に時間を節約できるだけでなく、一度しか保存されないため、メモリを節約することができます。
Rubyのシンボルはイミュータブル(変更できない)なので、調べるのがとても簡単です。
短い回答です。
シンボルを使用すると、比較の際に時間を節約できるだけでなく、一度しか保存されないため、メモリの節約にもなります。
Rubyのシンボルは 基本的に "イミュータブルストリングス"。 また、ソースコードの中で同じシンボルが何度も参照される場合、常に同じエンティティとして保存されることを意味します(例:同じオブジェクトIDを持つ)。
一方、文字列はミュータブルです。 つまり、いつでも変更することができるのです。例えば、ソースコードの中で何度も "name" という文字列が登場する場合、Ruby ではこれらをすべて別々の String オブジェクトに格納する必要があります。
文字列をHashのキーとして使う場合、Rubyは文字列を評価してその内容を調べ(そしてそれに対してハッシュ関数を計算し)、その結果を既にHashに格納されているキーの(ハッシュ化された)値と比較する必要があります。
シンボルをHashのキーとして使う場合、それがイミュータブルであることは暗黙の了解なので、Rubyは基本的に(ハッシュ関数の)オブジェクトIDと、すでにHashに格納されているキーの(ハッシュ化した)オブジェクトIDを比較すればいいのです。(ずっと速い)
デメリット 各シンボルは Ruby インタープリタのシンボルテーブルのスロットを消費し、それは決して解放されない。 シンボルは決してゴミとして回収されない。 そのため、大量のシンボル(自動生成されたものなど)がある場合は、この限りではありません。この場合、Rubyインタプリタのサイズにどのような影響を与えるかを評価する必要があります。
注意事項
文字列比較をする場合、Rubyはシンボルを評価することなく、オブジェクトIDを比較するだけで比較することができます。これは、評価する必要がある文字列の比較よりずっと速い。
ハッシュにアクセスする場合、Rubyは常にハッシュ関数を適用して、どんなキーからでも"ハッシュキー"を計算します。MD5-hashのようなものだ。 そして、Rubyはそのハッシュ化されたキー同士を比較する。
コード内で文字列を使用するたびに、新しいインスタンスが作成されます。文字列の作成は、シンボルを参照するよりも遅いです。
Ruby 2.1 からは、フリーズした文字列を使用する場合、Ruby は同じ文字列オブジェクトを使用します。これにより、同じ文字列の新しいコピーを作成する必要がなくなり、ガベージコレクションされるスペースに格納されます。
長い回答です。
関連
-
[解決済み] なぜパスワードにはStringではなくchar[]が好まれるのですか?
-
[解決済み] Rubyのswitch文の書き方
-
[解決済み] JavaScriptで二重引用符と単一引用符はいつ使うべきですか?
-
[解決済み] YAML の文字列を複数行に渡って分割するには?
-
[解決済み] JavaScriptで数値を文字列に変換するのに最適な方法は何ですか?
-
[解決済み] .soファイル内のシンボルを一覧表示する方法
-
[解決済み] Rubyのattr_accessor, attr_reader, attr_writerを使う理由は?
-
[解決済み】文字列中のある文字の出現回数をカウントする
-
[解決済み】ハッシュで文字列を記号に変換する最適な方法
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Rubyでファイルをあるディレクトリから別のディレクトリにコピーする
-
[解決済み] ルビーオールウェイズ ラウンドアップ
-
[解決済み] git, Heroku: pre-receive フックの減少
-
[解決済み] Rubyでnil値をマッピングして削除する方法
-
[解決済み] Ruby Detect方式
-
[解決済み] nil から String への暗黙の変換ができないエラー
-
[解決済み] rubyでto_yamlに書式オプションを指定することはできますか?
-
[解決済み] 文字列の文字をアルファベット順に並べるには?
-
[解決済み] gemのインストール中に "permission denied "エラーが発生するのはなぜですか?
-
[解決済み] ネストされたクラスとモジュールにネストされたクラスはいつ使用するのですか?