繁体   English   中英

Python:排序时处理异常

[英]Python: Handling exceptions while sorting

我有一个对象列表,我需要根据一个关键功能进行排序。 问题是列表中的某些元素在排序时可能会“过时”。 在这样一个过期的项目上调用key函数时,它会因异常而失败。

理想情况下,我想要的是一种使用键函数对列表进行排序的方法,以便在调用元素上的键函数时发生错误时,此元素将从排序结果中排除。

我可以使用以下示例重建我的问题:假设我有两个类, GoodBad

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM