[英]Python: Handling exceptions while sorting
我有一个对象列表,我需要根据一个关键功能进行排序。 问题是列表中的某些元素在排序时可能会“过时”。 在这样一个过期的项目上调用key函数时,它会因异常而失败。
理想情况下,我想要的是一种使用键函数对列表进行排序的方法,以便在调用元素上的键函数时发生错误时,此元素将从排序结果中排除。
我可以使用以下示例重建我的问题:假设我有两个类, Good
和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'
我想根据它们的x
属性对这些类的实例进行排序。 例如。:
>>> sorted([Good(5), Good(3), Good(7)], key=lambda obj: obj.x)
[Good(3), Good(5), Good(7)]
现在,当我的列表中存在Bad
时,排序失败:
>>> sorted([Good(5), Good(3), Bad()], key=lambda obj: obj.x)
... RuntimeError
我正在寻找一个神奇的函数func
,它根据键函数对列表进行排序,但只是忽略了键函数引发错误的元素:
>>> func([Good(5), Good(3), Bad()], key=lambda obj: obj.x)
[Good(3), Good(5)]
实现这一目标的最恐怖的方式是什么?
我知道的每个排序算法都不会抛出一些值,因为它们已经过时了。 排序算法的任务是对列表进行排序 ,并快速排序,其他一切都是无关紧要的,具体的任务。
所以,我会自己写这个神奇的功能。 它将分两步进行排序:首先它将过滤列表,只保留Good
值,然后对结果列表进行排序。
我用mergesort做了一次。 Mergesort使消除不再有用的值变得相对简单。
我做的项目是http://stromberg.dnsalias.org/~dstromberg/equivalence-classes.html#python-3e 。 随意突袭它的想法,或提出代码; 它在演讲中是免费的(GPLv2或更高版本,根据您的选择)。
该代码中的排序几乎应该按照您的要求进行,除非它将带有重复项的列表排序到列表列表,其中每个子列表具有相同的值。 那部分可能对你有用,也可能没用。
我有一个更简单的归并(它不会做重复的桶的东西,但它不会有滴不再视为良好的价值观要么处理)在http://stromberg.dnsalias.org/svn/sorts/比较/ trunk / 。 该文件是.m4,但不要让那个愚弄你 - 它是真正纯粹的python或cython从同一个.m4文件自动生成。
由于键函数的结果可能会随着时间的推移而发生变化,并且大多数排序实现可能会假设一个确定性的键函数,因此最好只对每个对象执行一次键函数,以确保有序且无崩溃的最终列表。
def func(seq, **kargs):
key = kargs["key"]
stored_values = {}
for item in seq:
try:
value = key(item)
stored_values[item] = value
except RuntimeError:
pass
return sorted(stored_values.iterkeys(), key=lambda item: stored_values[item])
print func([Good(5), Good(3), Bad()], key=lambda obj: obj.x)
结果:
[Good(3), Good(5)]
如果列表项在排序时可以从好到坏,那么您无能为力。 在排序之前, key
只被评估一次,因此键中的任何更改对于sort函数都是不可见的:
>>> from random import randrange
>>> values = [randrange(100) for i in range(10)]
>>> values
[54, 72, 91, 73, 55, 68, 21, 25, 18, 95]
>>> def k(x):
... print x
... return x
...
>>> values.sort(key=k)
54
72
91
73
55
68
21
25
18
95
(如果在排序过程中对键进行了多次评估,您会看到多次打印数字)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.