sorted([2, float('nan'), 1]) 返回 [2, nan, 1]

(至少在Activestate Python 3.1实现上。)

我明白 nan 是一个怪异的对象,因此,如果它在类似的结果中随机位置出现,我不会感到惊讶。但这也弄乱了容器中的非nan数字的排序,这确实是出乎意料的。

我问一个 相关问题 关于 max, ,基于这一点,我明白了为什么 sort 这样的工作。但这应该被视为一个错误吗?

文档只是说“返回新的排序列表[...]”,而无需指定任何详细信息。

编辑:我现在同意这不违反IEEE标准。但是,从任何常识角度来看,这都是一个错误。即使是Microsoft,也不知道经常承认自己的错误,但也将其视为错误,并将其修复在最新版本中: http://connect.microsoft.com/visualstudio/feedback/details/363379/bug-in-list-double-double-ind-sort-in-list-list-list-who------------------------.

无论如何,我最终跟随 @khachik的答案:

sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)

我怀疑与默认情况下这样做的语言相比,这会导致性能打击,但至少它起作用(禁止我引入的任何错误)。

有帮助吗?

解决方案

先前的答案很有用,但也许尚不清楚问题的根源。

在任何语言中,排序都应用给定的订单,由比较函数或以其他方式定义的输入值域上定义。例如,比人少,又名 operator <, 可以在整个过程中使用,并且只有少于定义在输入值上的合适订购。

但这对于浮点值而不是不少于浮点:“ NAN是无序的:它不等于,大于或少于任何东西,包括本身。” ((从GNU C手册中清晰的散文, 但适用于所有现代 IEEE754 基于 浮点)

因此,可能的解决方案是:

  1. 首先删除NAN,使输入域通过<(或使用其他分类功能)良好定义
  2. 定义确实定义NAN的订购的自定义比较函数(又称谓词),例如小于任何数字或大于任何数字。

任何语言都可以使用任何一种方法。

实际上,考虑到Python,如果您不太关心最快的性能,或者是否删除NAN是上下文中的一种所需行为,我希望删除NAN。

否则,您可以在较旧的Python版本中通过“ CMP”使用合适的谓词功能,或者通过此和 functools.cmp_to_key(). 。后者自然而然地比先删除NAN更尴尬。并需要注意避免 更差 在定义此谓词功能时性能。

其他提示

问题在于,如果列表包含一个NAN,则没有正确的顺序,因为序列A1,A2,A3,...,如果A1 <= A2 <= A3 <= ... <= AN进行排序。如果这些值中的任何一个是nan,则排序的属性断开,因为对于所有a,a <= nan和nan <= a都是错误的。

我不确定该错误,但是解决方法可能是以下内容:

sorted(
    (2, 1, float('nan')),
    lambda x,y: x is float('nan') and -1 
                or (y is float('nan') and 1
                or cmp(x,y)))

哪个导致:

('nan', 1, 2)

或删除 nan在排序或其他任何东西之前。

IEEE754是在这种情况下定义浮点操作的标准。该标准定义了操作数的比较操作,至少是其中一个是NAN的错误。因此,这不是错误。在进行阵列之前,您需要处理NAN。

假设您想保留NAN并将其订购为最低的“值”,那么这是一种解决方法 非唯一的南, 独特的numpy nan, 数值非数值 对象:

def is_nan(x):
    return (x is np.nan or x != x)

list_ = [2, float('nan'), 'z', 1, 'a', np.nan, 4, float('nan')]
sorted(list_, key = lambda x : float('-inf') if is_nan(x) else x)
# [nan, nan, nan, 1, 2, 4, 'a', 'z']
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top