2012-02-18 7 views
45

Rubyハッシュでシャベル(<<)演算子はどのように動作しますか?私は<code>about_hashes.rb</code>で、この時に来たとき、私は、<a href="http://rubykoans.com/">Ruby Koans tutorial series</a>を経た

def test_default_value_is_the_same_object 
    hash = Hash.new([]) 

    hash[:one] << "uno" 
    hash[:two] << "dos" 

    assert_equal ["uno", "dos"], hash[:one] 
    assert_equal ["uno", "dos"], hash[:two] 
    assert_equal ["uno", "dos"], hash[:three] 

    assert_equal true, hash[:one].object_id == hash[:two].object_id 
end 

assert_equals内の値は、チュートリアルでは、期待したもの、実際にあります。しかし、<<オペレーターと=オペレーターの違いはどのように分かりますか?

私の期待ということであった:

  • hash[:one]["uno"]
  • hash[:two]["dos"]
  • hash[:three][]

だろうだろうだろう私の期待が間違っていた理由を誰かが説明していただけますか?

+4

面白い、それはまさに私が期待したものです。それで、山は再び山だけだった。 –

答えて

52

hash = Hash.new([])を実行しているときは、デフォルト値がすべてのキーに対してまったく同じArrayインスタンスであるハッシュを作成しています。したがって、存在しないキーにアクセスするときはいつでも、同じ配列が返されます。

h = Hash.new([]) 
h[:foo].object_id # => 12215540 
h[:bar].object_id # => 12215540 

あなたは、キーごとに配列をしたい場合は、あなたがHash.newのブロック構文を使用する必要があります。

h = Hash.new { |h, k| h[k] = [] } 
h[:foo].object_id # => 7791280 
h[:bar].object_id # => 7790760 

編集:はまたGazlerが#<<方法に関して言っているものを見ると、どのオブジェクトで実際に呼び出すかを指定します。

+1

+1はobject_idを使って参照を表示します。 – Gazler

+0

ありがとうございました。したがって、元の空の配列はデフォルト値として格納されているオブジェクトです。そして、私たちは 'nil'の代わりに元のオブジェクトを取り戻し続けます。ニート!両方の回答(あなたと@Gazler)のおかげで、両方をupvotingしかし、これを受け入れる。 – bits

58

これは少し混乱しています。まず、ハッシュには<<メソッドがありません。この例のメソッドは配列に存在します。

コンストラクタを介してデフォルト値をハッシュに渡しているため、コードでエラーが発生しない理由があります。 http://ruby-doc.org/core-1.9.3/Hash.html#method-c-new

hash = Hash.new([]) 

これは、キーが存在しない場合、それは配列を返すことを意味します。次のコードを実行する場合:

hash = {} 
hash[:one] << "uno" 

次に、定義されていないメソッドエラーが発生します。

だからあなたの例では、どのような実際に起こっていることである。

hash = Hash.new([]) 

hash[:one] << "uno" #hash[:one] does not exist so return an array and push "uno" 
hash[:two] << "dos" #hash[:two] does not exist, so return the array ["uno"] and push "dos" 

それはその値への参照を格納するため、あなたが期待することとして、各時間は、ある一つの要素を持つ配列を返さない理由あなたはコンストラクタに渡されます。要素がプッシュされるたびに、初期配列を変更することを意味します。

+2

ありがとう@ gazler。これは明確にするのに役立ちました。 – bits

+1

ありがとうございます – Etch

+4

これは受け入れられる回答である必要があります。はるかに明確な説明。ありがとう –

関連する問題