Явор обнови решението на 11.04.2012 15:54 (преди над 12 години)
+class BiDict:
+
+ """Class that is a dictionary in both directions:
+ Both keys and values are unique and reversing
+ the order of (key, value) is possible (it can
+ be seen as finding the inverse of a discrete
+ function).
+ Complexity guarantees:
+ reverse() is O(1).
+ Normal dict operations are of the same asymptotic
+ complexity as the original dict implementation.
+ Implementation note: this class does not inherit
+ from dict, since the Liskov substitution principle
+ would be violated"""
+
+ def __init__(self, dictionary=None):
+ if dictionary == None:
+ dictionary = {}
+ self._forward_dict = {}
+ self._rev_dict = {}
+ f_dict = self._forward_dict
+ r_dict = self._rev_dict
+ try:
+ for (k, v) in dictionary.items():
+ if v in r_dict:
+ del f_dict[r_dict[v]]
+ f_dict[k] = v
+ r_dict[v] = k
+ except AttributeError:
+ raise TypeError
+
+ def inverse(self):
+ new_f_dict = self._rev_dict
+ self._rev_dict = self._forward_dict
+ self._forward_dict = new_f_dict
+
+ def __len__(self):
+ return len(self._forward_dict)
+
+ def __eq__(self, other):
+ return self._forward_dict == other._forward_dict
+
+ def __ne__(self, other):
+ return self._forward_dict != other._forward_dict
+
+ def __repr__(self):
+ return "BiDict({0})".format(self._forward_dict.__repr__())
+
+ def __iter__(self):
+ return iter(self._forward_dict)
+
+ def __contains__(self, key):
+ return self._forward_dict.__contains__(key)
+
+ def __delitem__(self, key):
+ value = self._forward_dict[key]
+ del self._forward_dict[key]
+ del self._rev_dict[value]
+
+ def __getitem__(self, key):
+ return self._forward_dict[key]
+
+ def __setitem__(self, key, value):
+ f_dict = self._forward_dict
+ r_dict = self._rev_dict
+ if key in f_dict:
+ del r_dict[f_dict[key]] # fix
+ if value in r_dict:
+ del f_dict[r_dict[value]] # fix
+ f_dict[key] = value
+ r_dict[value] = key
+
+ def __reduce__(self):
+ raise TypeError("can't pickle %s objects" % self.__class__.__name__)
+
+ def __reduce_ex__(self):
+ raise TypeError("can't pickle %s objects" % self.__class__.__name__)
+
+ def clear(self):
+ self._forward_dict = {}
+ self._rev_dict = {}
+
+ def copy(self):
+ return BiDict(self._forward_dict)
+
+ def get(self, key):
+ return self.__getitem__(key)
+
+ def items(self):
+ return self._forward_dict.items()
+
+ def keys(self):
+ return self._forward_dict.keys()
+
+ def pop(self, key, default=None):
+ if default == None or self._forward_dict.__contains__(key):
+ val = self._forward_dict.pop(key)
+ del self._rev_dict[val]
+ return val
+ else:
+ return default
+
+ def popitem(self):
+ kv_pair = self._forward_dict.popitem()
+ del self._rev_dict[kv_pair[1]]
+ return kv_pair
+
+ def update(self, E=None, **F):
+ if E == None:
+ E = []
+ try:
+ e_keys = E.keys()
+ for k in E:
+ self.__setitem__(k, E[k])
+ except AttributeError:
+ for (k, v) in E:
+ self.__setitem__(k, v)
+ for k in F:
+ self.__setitem__(k, F[k])
+
+ def values(self):
+ return self._forward_dict.values()