我试图在python中比较包含nan
的两个集合,但是因为{float('nan')} != {float('nan')}
而努力这样做。例如:
s1 = {float('nan'), 1}
s2 = {float('nan'), 1, 2}
assert set.issubset(s1, s2)
我得到一个断言错误。我怎么处理这个?
答案 0 :(得分:3)
一种方法:在相等之前测试身份(例如,请参阅文档中的here),因此如果您使用相同 nan
,它就会起作用:< / p>
>>> nan = float("nan")
>>> s1 = {nan, 1}
>>> s2 = {nan, 1, 2}
>>> set.issubset(s1, s2)
True
即使
>>> s1 = {float("nan"), 1}
>>> s2 = {float("nan"), 1, 2}
>>> set.issubset(s1, s2)
False
使用nan
非常尴尬,我会尽量避免将它们置于集合中并切换到不同的规范形式。但你可以随时确保它是同一个:
>>> def one_nan(x, nan=float("nan")):
... return nan if math.isnan(x) else x
...
>>> set.issubset(set(map(one_nan, s1)), set(map(one_nan, s2)))
True
或相同的千种变体。 (我有时会使用x != x
作为纳米检测的捷径,但在这里明确表示可能是一个好主意。)
答案 1 :(得分:2)
创建删除了所有nan
值的临时集,并将其进行比较。然后,分别处理nan
比较。例如,您可以检查两个原始集是否都包含nan
。
即使您可以在没有断言异常的情况下对集合执行比较,float('nan') == float('nan')
也会返回False
,因此从此集合比较中获得的价值很小(它会使比较的其余部分无效) 。您可以通过打印set.issubset
来检查此行为。
s1 = frozenset({float('nan'), 1})
s2 = frozenset({float('nan'), 1, 2})
print frozenset.issubset(s1,s2)
打印False
。
虽然set
is deprecated,但您可以按如下方式生成临时集:
s3 = set([value for value in s1 if not math.isnan(value)])
(根据需要重复每个临时集)
答案 2 :(得分:2)
您也可以为此编写一个简单的函数。请注意,float('nan') == float('nan')
的{{1}}为假;要检查是否有任何元素为nan,我们只需将其与自身进行比较。
nan
您可以简化def is_subset(s1, s2):
no_nan_set = lambda s: {x for x in s if x == x}
s1_nan, s2_nan = no_nan_set(s1), no_nan_set(s2)
if s1_nan != s1 and s2_nan != s2:
return s1_nan.issubset(s2_nan)
elif s1_nan == s1 and s2_nan == s2:
return s1.issubset(s2)
else:
return False
块
if-elif-else
请注意,如果您的任何一个集合中有两个或更多def is_subset(s1, s2):
no_nan_set = lambda s: {x for x in s if x == x}
s1_nan, s2_nan = no_nan_set(s1), no_nan_set(s2)
return (s1_nan != s1 and s2_nan != s2 and s1_nan.issubset(s2_nan)) \
or (s1_nan == s1 and s2_nan == s2 and s1.issubset(s2))
s(因为nan
),这将正常工作,同样如果float('nan') != float('nan')
的{{1}} id
是不同的。最后,即使你的一套或两套都没有nan
,这也会有效。