1. ホーム
  2. ruby

[解決済み] Rubyで記号をハッシュキーとして使う理由とは?

2022-04-23 03:46:08

質問

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 は同じ文字列オブジェクトを使用します。これにより、同じ文字列の新しいコピーを作成する必要がなくなり、ガベージコレクションされるスペースに格納されます。

長い回答です。

https://web.archive.org/web/20180709094450/http://www.reactive.io/tips/2009/01/11/the-difference-between-ruby-symbols-and-strings

http://www.randomhacks.net.s3-website-us-east-1.amazonaws.com/2007/01/20/13-ways-of-looking-at-a-ruby-symbol/

https://www.rubyguides.com/2016/01/ruby-mutability/