Python: sorting Intervals with __cmp__, with __lt__ meaning “strictly less than”
我有一个
我有一个
我对这种行为做了30次测试,一切都很顺利…
问题…除非我必须排序:
1 2 | >>> sorted([Interval(0, 10), Interval(-10, 5)]) [Interval(0, 10), Interval(-10, 5)] # WRONG! |
因为python使用
1 2 | >>> sorted([Interval(0, 10), Interval(-10, 5)], cmp=Interval.__cmp__) [Interval(-10, 5), Interval(0, 10)] # RIGHT |
在python3中,语法更加繁琐(在python2.6中不可用,在python2.7中可用)。
1 2 | >>> from functools import cmp_to_key >>> sorted([Interval(0, 10), Interval(-10, 5)], key=cmp_to_key(Interval.__cmp__)) |
我想要什么
我有没有办法让
1 2 | >>> sorted([Interval(0, 10), Interval(-10, 5)]) # no extra arguments! [Interval(-10, 5), Interval(0, 10)] |
附件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | def __cmp__(self, other): """ Tells whether other sorts before, after or equal to this Interval. Sorting is by begins, then by ends, then by data fields. If data fields are not both sortable types, data fields are compared alphabetically by type name. :param other: Interval :return: -1, 0, 1 :rtype: int """ s = self[0:2] try: o = other[0:2] except: o = (other,) if s != o: return -1 if s < o else 1 try: if self.data == other.data: return 0 return -1 if self.data < other.data else 1 except TypeError: s = type(self.data).__name__ o = type(other.data).__name__ if s == o: return 0 return -1 if s < o else 1 def __lt__(self, other): """ Less than operator. Returns False if there is an overlap. :param other: Interval or point :return: True or False :rtype: bool """ return not self.overlaps(other) and self.end <= other |
PS:这个问题在开发部门,我想把
- (2014-12):现在在我的开发部门,我提供
Interval.sorted 和Interval.key 。不过,仍然不那么优雅。我仍在寻找更好的方法!
我强烈建议不要为您的类定义任何订单运算符。
原因是,顺序运算符的存在意味着顺序关系及其相关语义的存在,而您的类本质上违反了这些语义(间隔上没有定义良好的顺序关系)。
例如,订单关系意味着:
1 | not(a<b) and not(b a==b |
这对区间来说是不正确的。
换言之,您不应该仅仅决定您希望运算符的含义(例如,
您应该做的是定义用于比较的非运算符方法(例如
1 2 | def sort_intervals(lst): return sorted(lst, cmp = ...) |