Is there a key that will always be the last when sorting a dictionary?

I have a dictionary with many keys, and I would like to add a dummy key that should always be the last one when the dictionary is sorted. And the sort is case insensitive. I was thinking about using the last word in the dictionary 'zyzzyva'

. Will this work? And what if my keys are directory paths where they might have / ,. Etc.

+3


source to share


2 answers


You can create an ad-hoc object that is always the last one to sort:

import functools

@functools.total_ordering
class Last(object):

    def __eq__(self, other):
        return False

    def __lt__(self, other):
        return False

      

Here's a usage example:

>>> sorted([Last(), 'c', 'a', 'b'])
['a', 'b', 'c', <__main__.Last object at 0x7f8db518d2e8>]

      




If you require something that is a string, consider using '\xff'

. If all of your keys are alphanumeric (in the sense that they consist of the letters AZ and the numbers 0-9), then there is no way to display items larger than '\xff'

.

>>> sorted(['\xff', 'c', 'a', 'b'])
['a', 'b', 'c', 'ΓΏ']

      

Beware, however, that some encodings (including UTF-8) use a character '\xff'

.

If you are using Unicode strings (or are using Python 3) then u'\uffff'

might be a good alternative '\xff'

.

+9


source


I was thinking about using the last word in the dictionary "zyzzyva". Will this work?

Well, it depends on your data. Are your keys words in English? Then it will work. But if your keys can be arbitrary word-like strings, you can have 'zzz'

. Or, if they might be non-English words, you might have one that starts with the letter that comes after 'z'

. And if they aren't even words, they may have characters that come after any letter.

And since you said that your keys can be directory paths, they are clearly not all English words.


One possibility is to create a class whose members compare more than any string:



@functools.total_ordering
class StringInfinity(str):
    def __new__(cls):
        return str.__new__(StringInfinity, 'I am the biggest string')
    def __lt__(self, other): return False
    def __eq__(self, other): return isinstance(other, StringInfinity)

>>> s = StringInfinity()
>>> s
'I am the biggest string'
>>> s > 'zzz'
True

      


Note that there are some cases of edges where subclassing str

can be a problem, but I don't think you probably have to worry. *


* Several C extension modules expect a to str

be exactly a str

, not a subclass. If you pass all your keys to such a module, you will receive TypeError

. It is rare, easy to detect, and easy to work with (for example, just str(key)

instead key

). More seriously, it is possible that the C extension could simply assume that either str

is for sure str

without checking it and, say, directly compare the buffers. What will quietly do the wrong thing. I don't know if anyone has ever written such a module, and I don't know if you care about the comparison outside of the original call to sort the dict keys, but it would be harder to detect and work around if it did appear.

+2


source







All Articles