max*_*max 29 python sorting math nan
sorted([2, float('nan'), 1]) 回报 [2, nan, 1]
(至少在Activestate Python 3.1实现上.)
我理解这nan是一个奇怪的对象,所以如果它出现在排序结果中的随机位置,我不会感到惊讶.但它也混淆了容器中非纳米数的排序,这实在是出乎意料.
我问了一个相关的问题有关max,并根据我理解为什么sort是这样工作的.但是,这应该被视为一个错误吗?
文档只是说"返回一个新的排序列表[...]"而没有指定任何细节.
编辑:我现在同意这不违反IEEE标准.但是,我认为这是任何常识观点的错误.即使微软经常承认自己的错误,也已经认识到这个错误,并将其修复为最新版本:http://connect.microsoft.com/VisualStudio/feedback/details/363379/bug- in-list-double-sort-in-list-which-contains-double-nan.
无论如何,我最终关注@ khachik的回答:
sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)
Run Code Online (Sandbox Code Playgroud)
我怀疑它与默认情况下的语言相比会导致性能下降,但至少它可行(除非我介绍的任何错误).
小智 13
以前的答案很有用,但可能不清楚问题的根源.
在任何语言中,sort都应用由比较函数或以其他方式定义的给定排序,而不是输入值的域.例如,operator <,当且仅当小于定义输入值的合适排序时,小于,也可以全部使用.
但是对于浮点值并且小于:"NaN是无序的:它不等于,大于或小于任何东西,包括它自己." (来自GNU C手册的清晰散文,但适用于所有IEEE754基于现代的浮点)
所以可能的解决方案是:
- 首先删除NaNs,通过<(或正在使用的其他排序函数)很好地定义输入域
- 定义定义NaN排序的自定义比较函数(aka谓词),例如小于任何数字或大于任何数字.
这两种方法都可以用于任何语言.
实际上,考虑到python,如果你不关心最快的性能,或者如果在上下文中删除NaN是一种理想的行为,我宁愿删除NaN.
否则你可以在旧的python版本中通过"cmp"使用合适的谓词函数,或者通过这个和 functools.cmp_to_key().后者比首先去除NaN更加尴尬.和关怀将被要求避免糟糕的表现,定义这个谓词功能时.
小智 7
问题是如果列表包含NAN,则没有正确的顺序,因为如果a1 <= a2 <= a3 <= ... <= an,则对序列a1,a2,a3,...,a进行排序.如果这些值中的任何一个是NAN,则排序的属性会中断,因为对于所有a,<= NAN和NAN <= a都是假的.
假设您想保留 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']
Run Code Online (Sandbox Code Playgroud)
我不确定该错误,但解决方法可能如下:
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)))
Run Code Online (Sandbox Code Playgroud)
这导致:
('nan', 1, 2)
Run Code Online (Sandbox Code Playgroud)
或者nan在排序之前删除s或其他任何东西.