2014-04-03 56 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