Skip to content

Commit d1ef3ac

Browse files
committed
-
1 parent 5bfbd49 commit d1ef3ac

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

source_py3/python_toolbox/nifty_collections/ordered_dict.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
class OrderedDict(StdlibOrderedDict):
1616

17-
def sort(self, key=None, reversed=False):
17+
def sort(self, key=None, reverse=False):
1818
'''
1919
Sort the items according to their keys, changing the order in-place.
2020
@@ -23,9 +23,8 @@ def sort(self, key=None, reversed=False):
2323
'''
2424
key_function = \
2525
comparison_tools.process_key_function_or_attribute_name(key)
26-
sorted_keys = sorted(self.keys(), key=key_function)
27-
step = -1 if reversed else 1
28-
for key_ in sorted_keys[1::step]:
26+
sorted_keys = sorted(self.keys(), key=key_function, reverse=reverse)
27+
for key_ in sorted_keys[1:]:
2928
self.move_to_end(key_)
3029

3130

source_py3/python_toolbox/nifty_collections/ordered_set.py

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
import collections
1212

13+
from python_toolbox import comparison_tools
14+
15+
1316
KEY, PREV, NEXT = range(3)
1417

1518

@@ -22,49 +25,53 @@ class OrderedSet(collections.MutableSet):
2225
'''
2326

2427
def __init__(self, iterable=None):
25-
self.end = end = []
26-
end += [None, end, end] # sentinel node for doubly linked list
27-
self.map = {} # key --> [key, prev, next]
28+
self.clear()
2829
if iterable is not None:
2930
self |= iterable
3031

32+
33+
def clear(self):
34+
self._end = []
35+
self._end += [None, self._end, self._end]
36+
self._map = {}
37+
3138
def __len__(self):
32-
return len(self.map)
39+
return len(self._map)
3340

3441
def __contains__(self, key):
35-
return key in self.map
42+
return key in self._map
3643

3744
def add(self, key):
3845
"""
3946
Add an element to a set.
4047
4148
This has no effect if the element is already present.
4249
"""
43-
if key not in self.map:
44-
end = self.end
50+
if key not in self._map:
51+
end = self._end
4552
curr = end[PREV]
46-
curr[NEXT] = end[PREV] = self.map[key] = [key, curr, end]
53+
curr[NEXT] = end[PREV] = self._map[key] = [key, curr, end]
4754

4855
def discard(self, key):
4956
"""
5057
Remove an element from a set if it is a member.
5158
5259
If the element is not a member, do nothing.
5360
"""
54-
if key in self.map:
55-
key, prev, next = self.map.pop(key)
61+
if key in self._map:
62+
key, prev, next = self._map.pop(key)
5663
prev[NEXT] = next
5764
next[PREV] = prev
5865

5966
def __iter__(self):
60-
end = self.end
67+
end = self._end
6168
curr = end[NEXT]
6269
while curr is not end:
6370
yield curr[KEY]
6471
curr = curr[NEXT]
6572

6673
def __reversed__(self):
67-
end = self.end
74+
end = self._end
6875
curr = end[PREV]
6976
while curr is not end:
7077
yield curr[KEY]
@@ -92,3 +99,34 @@ def __del__(self):
9299
self.clear() # remove circular references
93100
# todo: is this really needed? i'm worried about this making the gc not
94101
# drop circulary-referencing objects.
102+
103+
def move_to_end(self, key):
104+
'''Move an existing element to the end (or beginning if last==False).
105+
106+
Raises KeyError if the element does not exist.
107+
When last=True, acts like a fast version of self[key]=self.pop(key).
108+
109+
'''
110+
# Inefficient implementation until someone cares.
111+
if key in self:
112+
self.remove(key)
113+
self.add(key)
114+
115+
116+
def sort(self, key=None, reverse=False):
117+
'''
118+
Sort the items according to their keys, changing the order in-place.
119+
120+
The optional `key` argument will be passed to the `sorted` function as
121+
a key function.
122+
'''
123+
# Inefficient implementation until someone cares.
124+
key_function = \
125+
comparison_tools.process_key_function_or_attribute_name(key)
126+
sorted_members = sorted(tuple(self), key=key_function, reverse=reverse)
127+
128+
self.clear()
129+
for member in sorted_members[1:]:
130+
self.move_to_end(member)
131+
132+

0 commit comments

Comments
 (0)