Search code examples
pythonrubydictionarylanguage-comparisonsautovivification

What's the Ruby equivalent of Python's defaultdict?


In Python, I can make a hash where each element has a default value when it's first referenced (also know as "autovivification"). Here's an example:

from collections import defaultdict
d = defaultdict(int)
d["new_key"] += 1
print d

Printing the dict shows the value for "new_key" is 1.

What's the equivalent in Ruby? This code throws an error:

d = {}
d[:new_key] += 1
puts d

test.rb:3:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)

Solution

  • You can use the first argument of the Hash.new method for that:

    d = Hash.new 0
    d[:new_key] += 1
    d[:new_key] #=> 1
    d[:foo]     #=> 0
    

    Be careful - you might accidentally change the default value:

    h = Hash.new("Go Fish")
    h[:unknown_key]         #=> "Go Fish"
    h[:unknown_key].upcase! #=> "GO FISH"
    h[:next_key]            #=> "GO FISH"
    

    As "mu is too short" pointed out in his answer, you should better use a proc, as in:

    h = Hash.new { |h, k| h[k] = 0 }