设置默认值

默认情况下,尝试查找不存在的键的值将返回 nil。当使用不存在的密钥访问散列时,你可以选择指定要返回的其他值(或要采取的操作)。虽然这被称为默认值,但它不必是单个值; 例如,它可以是计算值,例如密钥的长度。

哈希的默认值可以传递给它的构造函数:

h = Hash.new(0)

h[:hi] = 1 
puts h[:hi]  # => 1 
puts h[:bye] # => 0 returns default value instead of nil

也可以在已构造的哈希上指定默认值:

my_hash = { human: 2, animal: 1 }
my_hash.default = 0
my_hash[:plant] # => 0

请务必注意,每次访问新密钥时都不会复制默认值,这可能会在默认值为引用类型时导致令人惊讶的结果:

# Use an empty array as the default value
authors = Hash.new([])

# Append a book title 
authors[:homer] << 'The Odyssey'

# All new keys map to a reference to the same array:
authors[:plato] # => ['The Odyssey']

为避免此问题,Hash 构造函数接受每次访问新密钥时执行的块,并将返回的值用作默认值:

authors = Hash.new { [] }

# Note that we're using += instead of <<, see below
authors[:homer] += ['The Odyssey']
authors[:plato] # => []

authors # => {:homer=>["The Odyssey"]}

注意,上面我们必须使用+ =而不是<<因为默认值不会自动分配给哈希值; 使用<<会添加到数组中,但作者[:homer]将保持未定义:

authors[:homer] << 'The Odyssey' # ['The Odyssey']
authors[:homer] # => []
authors # => {}

为了能够在访问时分配默认值,以及计算更复杂的默认值,默认块将传递散列和密钥:

authors = Hash.new { |hash, key| hash[key] = [] }

authors[:homer] << 'The Odyssey'
authors[:plato] # => []

authors # => {:homer=>["The Odyssey"], :plato=>[]}

你还可以使用默认块来执行操作和/或返回取决于键(或其他一些数据)的值:

chars = Hash.new { |hash,key| key.length }

chars[:test] # => 4

你甚至可以创建更复杂的哈希:

page_views = Hash.new { |hash, key| hash[key] = { count: 0, url: key } }
page_views["http://example.com"][:count] += 1
page_views # => {"http://example.com"=>{:count=>1, :url=>"http://example.com"}}

要在已存在的哈希上将默认值设置为 Proc,请使用 default_proc=

authors = {}
authors.default_proc = proc { [] }

authors[:homer] += ['The Odyssey']
authors[:plato] # => []

authors # {:homer=>["The Odyssey"]}