从元组列表中获取具有“NaN”的元组索引

Posted

技术标签:

【中文标题】从元组列表中获取具有“NaN”的元组索引【英文标题】:Get index of tuple with "NaN" from list of tuples 【发布时间】:2021-04-25 19:56:38 【问题描述】:

我有一个元组列表,其中一个元素为NaN

l = [('a', 7.0), ('b', float('nan'))]

我想在上面的列表中找到元组('b', float('nan'))的索引。

l.index(('b', float('nan')) 无法在列表中找到该元素,即使它的索引为 1。它正在引发 ValueError 异常:

>>> l.index(('b', float('nan'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: ('b', nan) is not in list

这很可能是因为每个 float('nan') 都是一个独立的 NaN 对象,这意味着这两个元组也是不同的对象。

我一般如何解决这个问题?

【问题讨论】:

因为float('nan') == float('nan')返回False 【参考方案1】:

float('nan') == float('nan') 返回False,因为它被设计为不与自身匹配。这就是为什么list.index() 函数无法找到匹配NaN 值并引发ValueError 异常的原因。

请阅读Why is NaN not equal to NaN?以了解有关此行为的更多信息。

下面是一个自定义函数check_nan_match(),用于检查传递的对象是否具有相同的值。这个函数也可以根据上面的属性匹配NaN对象,即NaNs在匹配自身时返回False

# Function too check passed values are match, including `NaN`
def check_nan_match(a, b):
    return (b != b and a != a) or a == b
          # ^    ^ `NaN` property to return False when matched with itself

为了在包含NaNlist 中获取tuple 的索引,这里我创建了另一个自定义函数get_nan_index。此函数接受my_listmy_tuple 作为参数,遍历my_list 以获得my_tuple 的索引。为了检查相等性,我使用了之前创建的 check_nan_match 函数,它也能够匹配 NaN 值。

# Get index from list of tuple , when tuple is passed
def get_nan_index(my_list, my_tuple):
    for i, t in enumerate(my_list):
        if all(check_nan_match(x, y) for x, y in zip(t, my_tuple)):
            return i
    else:
        raise ValueError  # Raise `ValueError` exception in case of no match.
                          # Similar to `list.index(...)` function

示例运行:

# check for tuple with `NaN` 
>>> get_nan_index([('a', 7.0), ('b', float('nan'))], ('b', float('nan')))
1

# check for tuple without `NaN`
>>> get_nan_index([('a', 1), ('b', 2)], ('b', 2))
1

# `ValueError` exception if no match
>>> get_nan_index([('a', 7.0), ('b', 3)], ('b', float('nan')))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in get_nan_index
ValueError

【讨论】:

如果您只想要第一个短路索引,next(i for i, (x, y) in enumerate(l) if x == 'b' and isnan(y)) 会这样做(还要确保测试两个值)。 @ShadowRanger 在生成器中使用next() 处理不同的边缘情况不会很干净。在我看来,以我上面创建的自定义函数的形式使用它会更简洁

以上是关于从元组列表中获取具有“NaN”的元组索引的主要内容,如果未能解决你的问题,请参考以下文章

从元组的元组中创建一个列表

从元组python 3列表中只获取整数

使用min函数从元组列表中获取多个元组

删除元组列表中包含 nan 的元组——Python

如何根据元组的索引值从列表中删除重复的元组,同时保持元组的顺序? [复制]

元组列表(字符串,浮点数)与 NaN 如何获得最小值?