【问题标题】:How to search a list of arrays如何搜索数组列表
【发布时间】:2016-02-26 15:19:15
【问题描述】:

考虑以下两个数组的列表:

from numpy import array

a = array([0, 1])
b = array([1, 0])

l = [a,b]

然后找到a的索引正确给出

l.index(a)
>>> 0

虽然这不适用于b

l.index(b)
ValueError: The truth value of an array with more than one element is ambiguous. 
Use a.any() or a.all()

在我看来,调用列表的 .index 函数不适用于 numpy 数组列表。

有人知道解释吗? 到目前为止,我总是通过将数组转换为字符串来解决这个问题。有人知道更优雅、更快速的解决方案吗?

【问题讨论】:

  • 对于相同形状数组的列表,您可以使用 NumPythonic 搜索:np.nonzero((l == b).all(1))[0][0]
  • 发生这种情况是因为.index() 首先比较身份然后比较相等,它适用于a,因为a is l[0]True,但是当涉及到查找b 时,它以@ 结尾987654335@,现在 Python 在其上调用 bool()bool(b == l[0])。所以,l.index(array([0, 1])) 也会引发同样的错误。我已经在这里解释过了:stackoverflow.com/a/28815970/846892
  • 嗨,这个问题重复已经回答了,stackoverflow.com/a/1156114/4061269
  • @LiorDadon 我认为您建议的答案及其潜在问题都不能完全解决当前的问题。那里的 OP 没有提到数组,与这里相反,她甚至声明对于列表列表,['a','b'] in list 确实 工作。
  • @NotAnAmbiTurner 我打电话给.index on l,这仍然是一个列表。这里的重点不是l,而是它的元素是数组。

标签: python arrays list search numpy


【解决方案1】:

此错误来自 numpy 处理数组元素之间比较的方式,请参阅:link

所以我猜测,由于第一个元素是搜索的实例,因此您获得了它的索引,但尝试将第一个元素与第二个元素进行比较,您会收到此错误。

我认为你可以使用类似的东西:

[i for i, temp in enumerate(l) if (temp == b).all()]

要获得一个包含相等数组索引的列表,但由于我不是 python 专家,因此可能会有更好的解决方案(它似乎有效......)

【讨论】:

    【解决方案2】:

    好问题实际上是l.index[a] 如何返回正确的值。因为 numpy 数组以特殊方式处理相等性:l[1] == b 通过比较各个值返回一个数组而不是布尔值。这里它给出了array([ True, True], dtype=bool),它不能直接转换为布尔值,因此会出错。

    事实上,Python 使用丰富的比较,特别是PyObject_RichCompareBool 将搜索到的值与列表中的每个元素进行比较是序列,这意味着它首先测试身份(a is b)和下一个相等(a == b)。所以对于第一个元素,如a is l[0],标识为真,返回索引0。

    但是对于任何其他元素,与第一个元素的标识为假,并且相等性测试导致错误。 (感谢 Ashwini Chaudhary 在评论中的精彩解释)。

    您可以通过测试包含与l[0] 相同元素的数组的新副本来确认:

    d = array([0,1])
    l.index(d)
    

    它给出了同样的错误,因为身份是假的,并且相等性测试引发了错误。

    这意味着您不能依赖任何使用比较(索引、输入、删除)的列表方法,并且必须使用自定义函数,例如 @orestiss 提出的函数。或者,由于 numpy 数组列表似乎很难使用,您应该考虑包装数组:

    >>> class NArray(object):
        def __init__(self, arr):
            self.arr = arr
        def array(self):
            return self.arr
        def __eq__(self, other):
            if (other.arr is self.arr):
                return True
            return (self.arr == other.arr).all()
        def __ne__(self, other):
            return not (self == other)
    
    
    >>> a = array([0, 1])
    >>> b = array([1, 0])
    >>> l = [ NArray(a), NArray(b) ]
    >>> l.index(NArray(a))
    0
    >>> l.index(NArray(b))
    1
    

    【讨论】:

    • 第一个元素没有特殊情况,rich comparison 总是先比较身份。
    • PyObject_RichCompareBool 为每个项目调用,PyObject_RichCompareBool 首先比较身份,如果它们是不同的对象,它将在它们上调用PyObject_RichComparel.index(b) 基本上失败了,因为在比较了a(即l[0])和b 的身份之后,Python 在它们上尝试==,然后在其结果上调用bool() 失败。因此,它甚至永远不会到达第二个索引,否则它会返回 1。
    • @AshwiniChaudhary:感谢您的精彩解释。我已经相应地编辑了我的帖子。
    猜你喜欢
    • 1970-01-01
    • 2015-02-12
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    相关资源
    最近更新 更多