在Python集合中处理float(';nan';)的正确方法是什么?

在Python集合中处理float(';nan';)的正确方法是什么?,python,set,nan,Python,Set,Nan,数字float('nan')在Python集合中会导致一些严重的问题。例如,请看以下内容: S = set() S.add(float('nan')) S # {nan} S.add(float('nan')) S.add(float('nan')) S # {nan, nan, nan} len(S) # 3 集合应该每种类型只有一个条目,但每个float('nan')已作为单独的项添加。

数字
float('nan')
在Python集合中会导致一些严重的问题。例如,请看以下内容:

S = set()
S.add(float('nan'))
S                    # {nan}
S.add(float('nan'))
S.add(float('nan'))
S                    # {nan, nan, nan}
len(S)               # 3
集合应该每种类型只有一个条目,但每个
float('nan')
已作为单独的项添加。但当你试图移除它们时,事情变得更加复杂

float('nan') in S    # False
S.remove(float('nan'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: nan
S#中的
float('nan')为假
S.移除(浮动('nan'))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
关键错误:nan
好的,每个针对
float('nan')
的测试结果都是
False
,甚至
float('nan')==float('nan')
,但对集合的结果是违反直觉的(至少对我来说)。那么,在实践中如何解决以下三个问题:

  • 如果可能添加了
    float('nan')
    ,如何知道Python集中不同对象的数量
  • 如何知道集合是否包含
    浮点('nan')
  • 如何从集合中删除
    float('nan')

  • 答案是“以前总是检查,永远不要在集合中添加
    float('nan')
    ”吗?

    下面的代码可以工作

    请注意,它进行字符串比较,因此可能比本机集慢

    class NanFriendlyFloatSet(set):
        def __getattribute__(self,name):
            attr = object.__getattribute__(self, name)
            if hasattr(attr, '__call__'):
                def new_func(*args, **kwargs):
                    if attr.__name__ == 'add' and str(args[0]).lower() == 'nan':
                      return
                    result = attr(*args, **kwargs)
                    return result
                return new_func
            else:
                return attr
    
    S1 = NanFriendlyFloatSet()
    S1.add(float('nan'))
    S1.add(float('nan'))
    S1.add(float(34.6))
    S1.add(float('nan'))
    print(len(S1))
    for x in S1:
      print(x) 
    
    输出

    1
    34.6
    

    你真的需要存储NaNs吗?它们是如何使用的?如果值为NaN,则可以使用,并插入一个“指示符”值作为替代。避免不惜一切代价将NaN添加到
    集合中。要测试nan,请使用
    import math;print(math.isnan(float('nan'))
    这并不能直接解决这个问题,但有助于解释为什么@juanpa.arrivillaga是正确的:@Carcigenicate您通常不知道它。假设您可以解析丢失数据的大型文本文件,或者解析结果会产生
    float('nan')
    float('nan')
    的问题是,您通常根本不知道它们在那里。@gui11aume如果可能,您可能需要先进行检查,然后在找到它们后决定如何处理它们。就像我提到的,你可以用一个自定义的指示符来代替它们,比如
    NaN\u holder=object()
    ,然后
    如果math.isnan(n):s.add(NaN\u holder)else:s.add(n)
    ,然后在你实际使用数据后决定如何处理
    NaN\u holder
    。谢谢你的建议!如果有什么不同的话,我认为最好是用一个支架来代替它们,而不是忽略浮动('nan')
    ,正如@Carcigenicate所建议的那样。或者,您甚至可以抛出一个异常,强制用户在出现
    float('nan')
    时执行操作(在此之后,用户可以随心所欲)。