2011-04-27 30 views
12

nếu tôi có một cuốn từ điển như thế nàytra cứu Tuỳ chỉnh từ điển trong Python

>>> d = {10: 3, 100: 2, 1000: 1} 

tôi có thể gõ một cái gì đó như:

>>> d.get(10), d.get(100), d.get(1000) 
(3, 2, 1) 

Mặc dù tôi muốn rằng nếu chìa khóa trao không được tìm thấy, giá trị tương ứng để phím chính gần nhất được tôn trọng cho khóa được trả về:

>>> d.get(20), d.get(60), d.get(200) 
(3, 2, 2) 

Thay vì kết quả bằng Python là

(None, None, None) 

Cách Pythonic để thực hiện hành vi tôi mô tả là gì?

Cảm ơn

+2

Không phải là bản sao chính xác, nhưng hữu ích: http://stackoverflow.com/questions/2390827/how-to-properly-subclass-dict-and-override-get-set –

Trả lời

17

Bạn có thể bắt nguồn từ dict để thay đổi hành vi của các phương pháp get():

class ClosestDict(dict): 
    def get(self, key): 
     key = min(self.iterkeys(), key=lambda x: abs(x - key)) 
     return dict.get(self, key) 

d = ClosestDict({10: 3, 100: 2, 1000: 1}) 
print (d.get(20), d.get(60), d.get(200)) 

in

(3, 2, 2) 

Lưu ý rằng sự phức tạp của get() không còn là O (1), nhưng O (n).

+3

Điều này làm cho tra cứu O (n) mặc dù vậy, hãy sử dụng cẩn thận. Có lẽ bạn nên đặt cho nó một cái tên khác thay thế. – delnan

+0

+1: Điều đó nhanh chóng thanh lịch và đơn giản! –

+0

@delnan: Có đề xuất nào cho một cái tên hay không? –

6

bisect mô-đun cho phép tra cứu nhanh vị trí chèn trong danh sách được sắp xếp.

from bisect import bisect_right 

def closest_matches(data, query): 
    keys = sorted(data) 
    return [data[i] for i in (min(map(abs, (keys[p-1], keys[p]))) for p in (bisect_right(keys, k) for k in query))] 

>>> d = {10: 3, 100: 2, 1000: 1} 
>>> closest_matches(d, [20, 60, 200]) 
[3, 3, 2] 
Các vấn đề liên quan