class School
def initialize
@db = Hash.new([])
end
def db
@db
end
def add(student_name,student_grade)
@db[student_grade] = @db[student_grade] || Array.new
puts @db
@db[student_grade] << student_name
puts @db
end
end
This piece of code is giving me strange results. If there isn’t the key defined on the hash @db then a new array is not being allocated to the hash key instead it is picking the value of the array from previous array.
I think in Hash.new() case, each key shares the same value of the array with my piece of code.
If I use Hash.new() and the key is not present then how can I append a value to it?
When you pass an argument to Hash.new(argument) it will make that object the default value when trying to access any key that doesn’t exist
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #=> 100
h["c"] #=> "Go Fish"
# The following alters the single default object
h["c"].upcase! #=> "GO FISH"
h["d"] #=> "GO FISH"
h.keys #=> ["a", "b"]
# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #=> "Go Fish: c"
h["c"].upcase! #=> "GO FISH: C"
h["d"] #=> "Go Fish: d"
h.keys #=> ["c", "d"]
When you initialize you are creating a new hash and setting it’s default value to a new array. In your def add you trying to set @db[student_grade] to itself or a new array. However you defined the default value so @db[student_grade] will be set to the default object. I think this is what you want:
class School
attr_reader :db # This is a lovely shortcut for def db
def initialize
@db = Hash.new()
end
def add(student_name,student_grade)
@db[student_grade] ||= []
# Here we are setting the key to [] unless it already exists.
b[student_grade] << student_name
end
end
@DeviousDuck I understood your answer but in your h = Hash.new(“Go Fish”) example why do h.keys give only [“a”,b"] and not [“a”,“b”,“c”,“d”] ? Also in that example are h[“c”] and h[“d”] referencing the same default object?
So in the “go fish!” example h.keys is only returning the keys that have had values set to them. We never set a value for c or d, we only tried to access their values. Since we set a default value it knew what to return.
Your correct about them referencing the same default object. This is why if we try to change the object i.e. h[“c”].upcase! we end up with it being changed for everything.