2014-04-03 53 views
10

在Python中,可以读取字典/哈希键,同时将键设置为默认值(如果尚不存在)。等同于Python dict的Ruby哈希setdefault

例如:

>>> d={'key': 'value'} 
>>> d.setdefault('key', 'default') 
'value'           # returns the existing value 
>>> d.setdefault('key-doesnt-exist', 'default') 
'default'          # sets and returns default value 
>>> d 
{'key-doesnt-exist': 'default', 'key': 'value'} 

是否有使用Ruby等效哈希?如果不是,Ruby中的惯用方法是什么?

回答

8

一个哈希可以有一个缺省值或一个默认的Proc(当一个密钥不存在时被调用)。

h = Hash.new("hi") 
puts h[123] #=> hi 
# change the default: 
h.default = "ho" 

在上述情况下散列保持空白。

h = Hash.new{|h,k| h[k] = []} 
h[123] << "a" 
p h # =>{123=>["a"]} 

Hash.new([])不会工作,因为在相同的阵列(同同一物体)将被用于每个密钥。

+0

+1我刚刚输入这个答案。你打我:) –

2

Python中没有这个函数的等价物。您可以随时使用猴子修补得到这个功能:

class Hash 

    def setdefault(key, value) 
    if self[key].nil? 
     self[key] = value 
    else 
     self[key] 
    end 
    end 

end 

h = Hash.new 
h = { 'key' => 'value' } 
h.setdefault('key', 'default') 
# => 'value' 
h.setdefault('key-doesnt-exist', 'default') 
# => 'default' 

但是请记住,猴子补丁通常被视为禁忌,至少在某些代码的环境。

猴修补的黄金规则:只是因为你可以, 并不意味着你应该。

更习惯的方法是通过Hash constructor通过传递一个额外的块或值来定义默认值。

+0

Upvoted为那些想要相同行为的人。谢谢。 – gabrtv

1

你可以简单地pass a block to the Hash constructor

hash = Hash.new do |hash, key| 
    hash[key] = :default 
end 

当访问一个不存在的关键企图块将被调用。它将传递哈希对象和密钥。你可以随心所欲地做任何事情;设置键为默认值,获得从键的新值等

如果你已经有了一个Hash对象,你可以使用the default_proc= method

hash = { key: 'value' } 

# ... 

hash.default_proc = proc do |hash, key| 
    hash[key] = :default 
end 
+0

通常,我们看到它在单行上使用'{...}'编写,而不是在多行上使用'do ... end'。 –

3

不是为了在这里击败一匹死马,而是setDefault的行为更像是一个哈希上的抓取。它的行为与默认的散列操作不同。一旦您在散列上设置了默认值,任何缺少的键将使用该默认值。 setDefault并非如此。它仅存储一个缺失密钥的值,并且仅在找不到该密钥时才存储该值。这整个存储新的键值对片是它不同于获取。

与此同时,我们目前只是在做setDefault确实是这样的:

h = {} 
h['key'] ||= 'value' 

红宝石继续推动点回家:

h.default = "Hey now" 
h.fetch('key', 'default')      # => 'value' 
h.fetch('key-doesnt-exist', 'default')   # => 'default' 
# h => {'key' => 'value'} 
h['not your key']        # => 'Hey now' 

的Python:

h = {'key':'value'} 
h.setdefault('key','default')     # => 'value' 
h.setdefault('key-doesnt-exist','default')  # => 'default' 
# h {'key': 'value', 'key-doesnt-exist': 'default'} 
h['not your key']        # => KeyError: 'not your key' 
+1

当你给它一个'default'时,Ruby的'fetch'的行为更像Python的['get'](https://docs.python.org/2/library/stdtypes.html#dict.get)值。 'setdefault'的优点是*后面的*代码行可以假设它已经存在,并且可以假定'dict'除了那些明确添加的内容之外不包含任何密钥,这使得代码更清晰并且更易于阅读和管理。 – jpmc26