Ruby散列等价于Python dict setdefault

时间:2014-04-03 16:30:57

标签: python ruby dictionary hash

在Python中,可以读取字典/散列键,同时将键设置为默认值(如果尚不存在)。

例如:

>>> 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中的惯用方法是什么?

5 个答案:

答案 0 :(得分:10)

Hash可以有默认值或默认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([])不起作用,因为每个键都使用相同的数组(与相同的对象相同)。

答案 1 :(得分:3)

不要在这里击败死马,但setDefault的行为更像是对哈希的fetch。它的行为与默认对哈希的作用方式不同。在哈希上设置默认值后,任何缺少的键都将使用该默认值。 setDefault不是这种情况。它仅存储一个缺失密钥的值,并且仅在找不到该密钥时才存储。整个存储新的键值对是它与fetch的不同之处。

与此同时,我们目前正在做setDefault的工作:

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

Ruby继续开车回家:

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'

答案 2 :(得分: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定义默认值。

答案 3 :(得分: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

答案 4 :(得分:1)

如果您只想修改setdefault返回的值,则可以通过Hash#merge!来表示:

Python:

>>> d = {}
>>> d.setdefault("k", []).append("v")
>>> d
{'k': ['v']}

Ruby:

[28] pry(main)> h = {}
=> {}
[29] pry(main)> h.merge!(k: [:v]) { |_key, old, new| old.concat(new) }
=> {:k=>[:v]}
[30] pry(main)> h
=> {:k=>[:v]}