sumolib.datastructures.OrderedMultiSet
multi set with insertion-order iteration based on OrderedSet by Raymond Hettinger (c) , MIT-License [http://code.activestate.com/recipes/576694/]
1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 2# Copyright (C) 2011-2026 German Aerospace Center (DLR) and others. 3# This program and the accompanying materials are made available under the 4# terms of the Eclipse Public License 2.0 which is available at 5# https://www.eclipse.org/legal/epl-2.0/ 6# This Source Code may also be made available under the following Secondary 7# Licenses when the conditions for such availability set forth in the Eclipse 8# Public License 2.0 are satisfied: GNU General Public License, version 2 9# or later which is available at 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 12 13# @file OrderedMultiSet.py 14# @author Jakob Erdmann 15# @author Michael Behrisch 16# @date 2011-10-04 17 18""" 19multi set with insertion-order iteration 20based on OrderedSet by Raymond Hettinger (c) , MIT-License 21[http://code.activestate.com/recipes/576694/] 22""" 23from __future__ import absolute_import 24 25import collections 26try: 27 from collections.abc import MutableSet 28except ImportError: 29 from collections import MutableSet 30KEY, PREV, NEXT = range(3) 31 32 33class OrderedMultiSet(MutableSet): 34 35 def __init__(self, iterable=None): 36 self.end = end = [] 37 # sentinel node for doubly linked list 38 end += [None, end, end] 39 # key --> [(key, prev1, next1), (key, prev2, next2), ...] 40 self.map = collections.defaultdict(collections.deque) 41 self.size = 0 42 if iterable is not None: 43 self |= iterable 44 45 def __len__(self): 46 return self.size 47 48 def __contains__(self, key): 49 return key in self.map 50 51 def add(self, key): 52 self.size += 1 53 end = self.end 54 curr = end[PREV] 55 new = [key, curr, end] 56 curr[NEXT] = end[PREV] = new 57 self.map[key].append(new) 58 59 def discard(self, key): 60 if key in self.map: 61 self.size -= 1 62 deque = self.map[key] 63 key, prev, next = deque.popleft() 64 prev[NEXT] = next 65 next[PREV] = prev 66 if len(deque) == 0: 67 self.map.pop(key) 68 69 def __iter__(self): 70 end = self.end 71 curr = end[NEXT] 72 while curr is not end: 73 yield curr[KEY] 74 curr = curr[NEXT] 75 76 def __reversed__(self): 77 end = self.end 78 curr = end[PREV] 79 while curr is not end: 80 yield curr[KEY] 81 curr = curr[PREV] 82 83 def pop(self, last=True): 84 if not self: 85 raise KeyError('set is empty') 86 key = next(reversed(self)) if last else next(iter(self)) 87 self.discard(key) 88 return key 89 90 def __repr__(self): 91 if not self: 92 return '%s()' % (self.__class__.__name__,) 93 return '%s(%r)' % (self.__class__.__name__, list(self)) 94 95 def __eq__(self, other): 96 if isinstance(other, self.__class__): 97 return len(self) == len(other) and list(self) == list(other) 98 return set(self) == set(other) 99 100 def __del__(self): 101 self.clear() # remove circular references 102 103 def __sub__(self, other): 104 result = self.__class__() 105 for x in self: 106 result.add(x) 107 for x in other: 108 result.discard(x) 109 return result 110 111 def __or__(self, other): 112 result = self.__class__() 113 for x in self: 114 result.add(x) 115 for x in other: 116 result.add(x) 117 return result
class
OrderedMultiSet(collections.abc.MutableSet):
34class OrderedMultiSet(MutableSet): 35 36 def __init__(self, iterable=None): 37 self.end = end = [] 38 # sentinel node for doubly linked list 39 end += [None, end, end] 40 # key --> [(key, prev1, next1), (key, prev2, next2), ...] 41 self.map = collections.defaultdict(collections.deque) 42 self.size = 0 43 if iterable is not None: 44 self |= iterable 45 46 def __len__(self): 47 return self.size 48 49 def __contains__(self, key): 50 return key in self.map 51 52 def add(self, key): 53 self.size += 1 54 end = self.end 55 curr = end[PREV] 56 new = [key, curr, end] 57 curr[NEXT] = end[PREV] = new 58 self.map[key].append(new) 59 60 def discard(self, key): 61 if key in self.map: 62 self.size -= 1 63 deque = self.map[key] 64 key, prev, next = deque.popleft() 65 prev[NEXT] = next 66 next[PREV] = prev 67 if len(deque) == 0: 68 self.map.pop(key) 69 70 def __iter__(self): 71 end = self.end 72 curr = end[NEXT] 73 while curr is not end: 74 yield curr[KEY] 75 curr = curr[NEXT] 76 77 def __reversed__(self): 78 end = self.end 79 curr = end[PREV] 80 while curr is not end: 81 yield curr[KEY] 82 curr = curr[PREV] 83 84 def pop(self, last=True): 85 if not self: 86 raise KeyError('set is empty') 87 key = next(reversed(self)) if last else next(iter(self)) 88 self.discard(key) 89 return key 90 91 def __repr__(self): 92 if not self: 93 return '%s()' % (self.__class__.__name__,) 94 return '%s(%r)' % (self.__class__.__name__, list(self)) 95 96 def __eq__(self, other): 97 if isinstance(other, self.__class__): 98 return len(self) == len(other) and list(self) == list(other) 99 return set(self) == set(other) 100 101 def __del__(self): 102 self.clear() # remove circular references 103 104 def __sub__(self, other): 105 result = self.__class__() 106 for x in self: 107 result.add(x) 108 for x in other: 109 result.discard(x) 110 return result 111 112 def __or__(self, other): 113 result = self.__class__() 114 for x in self: 115 result.add(x) 116 for x in other: 117 result.add(x) 118 return result
A mutable set is a finite, iterable container.
This class provides concrete generic implementations of all methods except for __contains__, __iter__, __len__, add(), and discard().
To override the comparisons (presumably for speed, as the semantics are fixed), all you have to do is redefine __le__ and then the other operations will automatically follow suit.
OrderedMultiSet(iterable=None)
36 def __init__(self, iterable=None): 37 self.end = end = [] 38 # sentinel node for doubly linked list 39 end += [None, end, end] 40 # key --> [(key, prev1, next1), (key, prev2, next2), ...] 41 self.map = collections.defaultdict(collections.deque) 42 self.size = 0 43 if iterable is not None: 44 self |= iterable
def
add(self, key):
52 def add(self, key): 53 self.size += 1 54 end = self.end 55 curr = end[PREV] 56 new = [key, curr, end] 57 curr[NEXT] = end[PREV] = new 58 self.map[key].append(new)
Add an element.