I have a list of objects that I need to sort according to a key function. The problem is that some of the elements in my list can go "out-of-date" while the list is being sorted. When the key function is called on such an expired item, it fails with an exception.
Ideally, what I would like is a way of sorting my list with a key function such that when an error occurs upon calling the key function on an element, this element is excluded from the sort result.
My problem can be reconstructed using the following example: Suppose I have two classes, Good and Bad:
class Good(object):
def __init__(self, x):
self.x = x
def __repr__(self):
return 'Good(%r)' % self.x
class Bad(object):
@property
def x(self):
raise RuntimeError()
def __repr__(self):
return 'Bad'
I want to sort instances of these classes according to their x property. Eg.:
>>> sorted([Good(5), Good(3), Good(7)], key=lambda obj: obj.x)
[Good(3), Good(5), Good(7)]
Now, when there is a Bad in my list, the sorting fails:
>>> sorted([Good(5), Good(3), Bad()], key=lambda obj: obj.x)
... RuntimeError
I am looking for a magical function func that sorts a list according to a key function, but simply ignores elements for which the key function raised an error:
>>> func([Good(5), Good(3), Bad()], key=lambda obj: obj.x)
[Good(3), Good(5)]
What is the most Pythonic way of achieving this?
Every sorting algorithm I know doesn't throw out some values because they're outdated or something. The task of sorting algorithm is to sort the list, and sort it fast, everything else is extraneous, specific task.
So, I would write this magical function myself. It would do the sorting in two steps: first it would filter the list, leaving only Good values, and then sort the resulting list.
I did this once with a mergesort. Mergesort makes it relatively simple to eliminate no-longer-useful values.
The project I did it in is at http://stromberg.dnsalias.org/~dstromberg/equivalence-classes.html#python-3e . Feel free to raid it for ideas, or lift code out of it; it's Free as in speech (GPLv2 or later, at your option).
The sort in that code should almost do what you want, except it'll sort a list with duplicates to a list of lists, where each sublist has equal values. That part may or may not be useful to you.
I've got a more straightforward mergesort (it doesn't do the duplicate buckets thing, but it doesn't deal with dropping no-longer-good values either) at http://stromberg.dnsalias.org/svn/sorts/compare/trunk/ . The file is .m4, but don't let that fool you - it's really pure python or cython autogenerated from the same .m4 file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With