Array Hash in Ruby
I have one hash, where key is a string and value is an array of strings. I want something like this:
{"k1"=>["v1", "v2"], "k2"=>["v3", "v4"]} I have only one hash and one array to implement this. I encoded something like this:
hash1 = Hash.new arr = Array.new arr.push "v1" arr.push "v2" hash1["k1"] = arr #hash is like this: {"k1"=>["v1", "v2"] #Now I clear the array to read the new values arr. clear arr.push "v3" arr.push "v4" hash1["k2"] = arr puts hash1 #Output: {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]} #Notice that k1 value also got updated Then I changed one line:
hash1 = Hash.new arr = Array.new arr.push "v1" arr.push "v2" hash1["k1"] = arr arr = [] # ** This is the only changed line. Now k1 value is correct. ** arr.push "v3" arr.push "v4" hash1["k2"] = arr puts hash1 #Output: {"k1"=>["v1", "v2"], "k2"=>["v3", "v4"]} (which I wanted) Can someone please explain to me how this happens? I am very new to Ruby. Ideally, what is the correct way to code this problem?
This should show you what is happening ( object_id is your friend). (I added underscore in Object_id to make it easier to see the differences.)
hash1 = {} # => {} arr = ["v1", "v2"] # => ["v1", "v2"] arr.object_id # => 7016637_4343580 hash1["k1"] = arr # => ["v1", "v2"] hash1 # => {"k1"=>["v1", "v2"]} hash1["k1"].object_id # => 7016637_4343580 arr.clear # => [] arr.object_id # => 7016637_4343580 arr << "v3" << "v4" # => ["v3", "v4"] arr.object_id # => 7016637_4343580 hash1["k2"] = arr # => ["v3", "v4"] hash1 # => {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]} hash1["k1"].object_id # => 7016637_4343580 hash1["k2"].object_id # => 7016637_4166580 arr = [] # => [] arr.object_id # => 7016637_4036500 arr = ["v5", "v6"] # => ["v5", "v6"] arr.object_id # => 7016637_3989880 hash1 # => {"k1"=>["v3", "v4"], "k2"=>["v3", "v4"]} hash1["k1"].object_id # => 7016637_4343580 hash1["k2"] = arr # => ["v5", "v6"] hash1 # => {"k1"=>["v3", "v4"], "k2"=>["v5", "v6"]} hash1["k1"].object_id # => 7016637_4343580 hash1["k2"].object_id # => 7016637_3989880 The array you saved in the hash still references arr , so itβs clear that arr.clear and using arr.push will clear and add new values ββto the value stored in the hash. However, arr = [] , arr now refers to a new array that is different from the one stored in the hash.
And you can just add a new array to the hash with:
hash1["k2"] = ["v3", "v4"] or
hash1["k2"] = %w[v3 v4]