I have a dictionary ‘vcomments’ where the keys are non-sequential integers. When looping through the keys I need to do so in sorted, or reverse-sorted, order. Currently I use
for key_pt in sorted(self.view.vcomments.iterkeys()):
but I also need to find those keys (or the next key) that are beyond, or before, a certain number:
if direction == 'down':
sorted_pts = (key_pt for key_pt in sorted(self.view.vcomments.iterkeys()) if key_pt > curr_pt)
else:
sorted_pts = (key_pt for key_pt in reversed(sorted(self.view.vcomments.iterkeys())) if key_pt < curr_pt)
try:
next_pt = sorted_pts.next()
except StopIteration:
-
Is it possible for me to create an iterator class (using the iterator protocol) that will store the dictionary and enable me to loop through them in either forward, or reverse, order? I’m assuming/guessing that I might need to first assign an attribute-value that will indicate whether the next loop should be forward/reverse.
-
Can I include a generator-function (nested) within my iterator class that will enable me to retrieve the next key; that is, beyond or before a supplied integer-number?
-
Similarly, will there be a way for me to supply begin-and-end points and retrieve all keys that fall between these values (in sorted order)?
I apologise for asking three (although related) questions – an answer to the first would give me a start. And I’m not rude enough to expect a full solution, just an indication whether these are feasible targets for me.
Added: and I would still need to be able to retrieve a single, specific dictionary-item by its key.
I think the best data structure for your needs here is a skip list. I’ve never implemented one — always wanted to — but it looks to me like this has all of the things you need.
A skip list stores its items in sorted order. Making the base list a doubly linked list will allow forward and reverse iteration in O(n).
A skip list allows O(log n) insertions, modifications, deletions, and searches. That’s not quite so fast as a dictionary, but it seems to me that if you need the items stored in sorted order, a dictionary is going to give you trouble — even an
OrderedDict, unless you are very rarely adding keys.With some modifications described in the wikipedia article above, even indexed access can be implemented in O(log n).
There’s one implementation in Python here — there are probably others.
However, some of your comments suggest that you may be content with simply iterating over a sorted copy of your dictionary, and you’re just trying to clean up the above code. So here is one way to go about it. This is pretty naive, but it’s a starting point. This assumes you’re totally fine with O(n) search times and O(n log n) iteration times, which are both suboptimal…