Python dictionary - binary search for a key?

后端 未结 5 1320
长发绾君心
长发绾君心 2021-02-05 19:16

I want to write a container class that acts like a dictionary (actually derives from a dict), The keys for this structure will be dates.

When a key (i.e. date) is used t

5条回答
  •  囚心锁ツ
    2021-02-05 19:53

    You really don't want to subclass dict because you can't really reuse any of its functionality. Rather, subclass the abstract base class collections.Mapping (or MutableMapping if you want to also be able to modify an instance after creation), implement the indispensable special methods for the purpose, and you'll get other dict-like methods "for free" from the ABC.

    The methods you need to code are __getitem__ (and __setitem__ and __delitem__ if you want mutability), __len__, __iter__, and __contains__.

    The bisect module of the standard library gives you all you need to implement these efficiently on top of a sorted list. For example...:

    import collections
    import bisect
    
    class MyDict(collections.Mapping):
      def __init__(self, contents):
        "contents must be a sequence of key/value pairs"
        self._list = sorted(contents)
      def __iter__(self):
        return (k for (k, _) in self._list)
      def __contains__(self, k):
        i = bisect.bisect_left(self._list, (k, None))
        return i < len(self._list) and self._list[i][0] == k
      def __len__(self):
        return len(self._list)
      def __getitem__(self, k):
        i = bisect.bisect_left(self._list, (k, None))
        if i >= len(self._list): raise KeyError(k)
        return self._list[i][1]
    

    You'll probably want to fiddle __getitem__ depending on what you want to return (or whether you want to raise) for various corner cases such as "k greater than all keys in self".

提交回复
热议问题