📄 dictwithlists.py
字号:
# These are some handy dict types:## DictWithLists:# acts like a dict, but adding a key,value appends value to a list at that key# getting a value at a key returns the first value in the list# a key is only removed when the list is empty## OrderedDict:# just like a dict, but d.keys() is in insertion order## OrderedDictWithLists:# a combination of the two concepts that keeps lists at key locations in# insertion order## by Greg Hazel# with code from David Benjamin and contributersfrom BitTorrent.Lists import QListfrom BitTorrent.obsoletepythonsupport import setclass ReallyIterableDict(dict): # third level takes advantage of second level definitions def iteritems(self): for k in self: yield (k, self[k]) def iterkeys(self): return self.__iter__() # fourth level uses definitions from lower levels def itervalues(self): for _, v in self.iteritems(): yield v def values(self): return [v for _, v in self.iteritems()] def items(self): return list(self.iteritems()) class DictWithLists(ReallyIterableDict): def __init__(self, d = None, parent = ReallyIterableDict): self.parent = parent # python dict() can't take None if d: self.parent.__init__(self, d) else: self.parent.__init__(self) def popitem(self): try: key = self.keys()[0] except IndexError: raise KeyError('popitem(): dictionary is empty') return (key, self.pop(key)) def pop(self, key, *args): if key not in self and len(args) > 0: return args[0] l = self[key] data = l.popleft() # so we don't leak blank lists if len(l) == 0: self.parent.__delitem__(self, key) return data pop_from_row = pop def get_from_row(self, key): return self[key][0] def getrow(self, key): return self[key] def poprow(self, key): return self.parent.pop(self, key) def setrow(self, key, l): if len(l) == 0: return self.parent.__setitem__(self, key, l) def push(self, key, value): # a little footwork because the QList constructor is slow if key not in self: v = QList([value]) self.parent.__setitem__(self, key, v) else: self[key].append(value) push_to_row = push def keys(self): return self.parent.keys(self) def total_length(self): t = 0 for k in self.iterkeys(): t += len(self.getrow(k)) return tclass DictWithSets(DictWithLists): def pop(self, key, *args): if key not in self and len(args) > 0: return args[0] l = self[key] data = l.pop() # so we don't leak blank sets if len(l) == 0: self.parent.__delitem__(self, key) return data pop_from_row = pop def push(self, key, value): if key not in self: v = set([value]) self.parent.__setitem__(self, key, v) else: self[key].add(value) push_to_row = push def remove_fom_row(self, key, value): l = self[key] l.remove(value) # so we don't leak blank sets if len(l) == 0: self.parent.__delitem__(self, key) # from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747class OrderedDict(ReallyIterableDict): def __init__(self, d = None): self._keys = [] # python dict() can't take None if d: ReallyIterableDict.__init__(self, dict) else: ReallyIterableDict.__init__(self) def __delitem__(self, key): ReallyIterableDict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): ReallyIterableDict.__setitem__(self, key, item) if key not in self._keys: self._keys.append(key) def clear(self): ReallyIterableDict.clear(self) self._keys = [] def copy(self): newInstance = odict() newInstance.update(self) return newInstance def items(self): return zip(self._keys, self.values()) def keys(self): return self._keys[:] def __iter__(self): return iter(self._keys) def popitem(self): try: key = self._keys[-1] except IndexError: raise KeyError('dictionary is empty') val = self[key] self.parent.__delitem__(self, key) return (key, val) def setdefault(self, key, failobj = None): if key not in self._keys: self._keys.append(key) return ReallyIterableDict.setdefault(self, key, failobj) def update(self, dict): for (key,val) in dict.items(): self.__setitem__(key,val) def values(self): return map(self.get, self._keys)class OrderedDictWithLists(DictWithLists, OrderedDict): def __init__(self, dict = None, parent = OrderedDict): DictWithLists.__init__(self, dict, parent = parent) def __iter__(self): return iter(self._keys)if __name__=='__main__': d = DictWithLists() for i in xrange(50): for j in xrange(50): d.push(i, j) for i in xrange(50): for j in xrange(50): assert d.pop(i) == j od = OrderedDict() def make_str(i): return str(i) + "extra" for i in xrange(50): od[make_str(i)] = 1 for i,j in zip(xrange(50), od.keys()): assert make_str(i) == j odl = OrderedDictWithLists() for i in xrange(50): for j in xrange(50): odl.push(make_str(i), j) for i in xrange(50): for j in xrange(50): assert odl.pop(make_str(i)) == j od = OrderedDict() od['2'] = [1,1,1,1,1] od['1'] = [2,2,2,2,2] od['3'] = [3,3,3,3,3] k = od.keys()[0] assert k == '2' odl = OrderedDictWithLists() odl.setrow('2', [1,1,1,1,1]) odl.setrow('1', [2,2,2,2,2]) odl.setrow('3', [3,3,3,3,3]) k = odl.keys()[0] assert k == '2' od = OrderedDict() od['2'] = [1,1,1,1,1] od['1'] = [2,2,2,2,2] od['3'] = [3,3,3,3,3] r = [] for k in od.iterkeys(): r.append(k) assert r == ['2', '1', '3'] odl = OrderedDictWithLists() odl.setrow('2', [1,1,1,1,1]) odl.setrow('1', [2,2,2,2,2]) odl.setrow('3', [3,3,3,3,3]) r = [] for k in odl.iterkeys(): r.append(k) assert r == ['2', '1', '3'] d = DictWithLists() d.push(4, 3) d.push(4, 4) d.push(4, 2) d.push(4, 1) assert d.poprow(4) == QList([3,4,2,1])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -