2014-04-03 16 views
10

Trong Python, bạn có thể đọc từ điển/khóa băm trong khi đồng thời đặt khóa thành giá trị mặc định nếu giá trị chưa tồn tại.Mã băm Ruby tương đương với Python dict setdefault

Ví dụ:

>>> 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'} 

Có tương đương với Ruby băm? Nếu không, cách tiếp cận thành ngữ trong Ruby là gì?

Trả lời

8

Một Hash có thể có một giá trị mặc định hoặc một Proc mặc định (được gọi khi không có khóa).

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

Trong trường hợp trên, giá trị băm sẽ trống.

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

Hash.new([]) sẽ không hoạt động vì cùng một mảng (giống như đối tượng giống nhau) sẽ được sử dụng cho mỗi khóa.

+0

+1 Tôi vừa nhập câu trả lời này. Bạn đánh bại tôi :) –

2

Không có hàm nào tương đương với hàm này trong Python. Bạn luôn có thể sử dụng khỉ vá để có được chức năng này:

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' 

Nhưng hãy nhớ rằng khỉ vá thường được xem như một điều cấm kỵ, ít nhất là trong môi trường mã nhất định.

Quy tắc vàng miếng vá khỉ áp dụng: chỉ vì bạn có thể, không có nghĩa là bạn nên làm.

Cách thành ngữ hơn là xác định giá trị mặc định thông qua Hash constructor bằng cách chuyển khối hoặc giá trị bổ sung.

+0

upvoted cho những người muốn hành vi giống hệt nhau. Cảm ơn. – gabrtv

1

Bạn có thể chỉ đơn giản là pass a block to the Hash constructor:

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

Khối sẽ được gọi khi một nỗ lực để truy cập một chìa khóa không tồn tại được thực hiện. Nó sẽ được truyền đối tượng băm và khóa. Bạn có thể làm bất cứ điều gì bạn muốn với họ; thiết lập các chìa khóa cho một giá trị mặc định, lấy được một giá trị mới từ chìa khóa vv

Nếu bạn đã có một đối tượng Hash, bạn có thể sử dụng the default_proc= method:

hash = { key: 'value' } 

# ... 

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

Thông thường chúng ta thấy nó được viết bằng cách sử dụng '{...}' trên một dòng, thay vì 'do ... end' trên nhiều dòng. –

3

Không đánh bại một con ngựa chết ở đây, nhưng setDefault hoạt động giống như tìm nạp trên một băm. Nó không hoạt động theo cùng một cách mặc định trên một băm. Khi bạn đặt mặc định trên băm, bất kỳ khóa bị thiếu nào sẽ sử dụng giá trị mặc định đó. Đó không phải là trường hợp với setDefault. Nó lưu trữ giá trị cho chỉ một khóa bị mất và chỉ khi nó không tìm thấy khóa đó. Toàn bộ đó lưu trữ phần cặp giá trị khóa mới là nơi nó khác với tìm nạp.

Đồng thời, chúng tôi hiện chỉ làm những gì setDefault làm như thế này:

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

của Ruby tiếp tục lái xe điểm nhà:

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

'fetch' của Ruby hoạt động giống như [' get'] của Python (https://docs.python.org/2/library/stdtypes.html#dict.get) khi bạn cho nó một 'mặc định' giá trị. lợi thế của 'setdefault' là * các dòng * tiếp theo của mã có thể giả sử nó đã ở đó và có thể giả sử rằng' dict' không chứa khóa nào khác ngoài những khóa được thêm vào một cách rõ ràng, làm cho mã sạch hơn và dễ đọc và dễ quản lý hơn. – jpmc26

Các vấn đề liên quan