测试numpy数组是否为numpy数组列表的成员,并将其从列表中删除

时间:2018-10-30 13:20:19

标签: python arrays list numpy

在测试numpy数组c是否是numpy数组CNTS的成员时:

import numpy as np

c = np.array([[[ 75, 763]],
              [[ 57, 763]],
              [[ 57, 749]],
              [[ 75, 749]]])

CNTS = [np.array([[[  78, 1202]],
                  [[  63, 1202]],
                  [[  63, 1187]],
                  [[  78, 1187]]]),
        np.array([[[ 75, 763]],
                  [[ 57, 763]],
                  [[ 57, 749]],
                  [[ 75, 749]]]),
        np.array([[[ 72, 742]],
                  [[ 58, 742]],
                  [[ 57, 741]],
                  [[ 57, 727]],
                  [[ 58, 726]],
                  [[ 72, 726]]]),
        np.array([[[ 66, 194]],
                  [[ 51, 194]],
                  [[ 51, 179]],
                  [[ 66, 179]]])]

print(c in CNTS)

我得到:

  

ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()

但是,答案很明确:c恰好是CNTS[1],因此c in CNTS应该返回True!

如何正确测试numpy数组是否为numpy数组列表的成员?

删除时会发生相同的问题:

CNTS.remove(c)
  

ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()

应用程序:测试opencv轮廓(numpy数组)是否为轮廓列表的成员,例如参见Remove an opencv contour from a list of contours

3 个答案:

答案 0 :(得分:3)

您会收到错误消息,因为in实际上在bool(c == x)的每个元素x上调用CNTS。引发错误的是__bool__转换:

>>> c == CNTS[1]
array([[[ True,  True]],
       [[ True,  True]],
       [[ True,  True]],
       [[ True,  True]]])

>>> bool(_)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

删除操作同样适用,因为它会测试每个元素的相等性。

包含

解决方案是使用np.array_equal或对每个比较应用all方法:

any(np.array_equal(c, x) for x in CNTS)

OR

any((c == x).all() for x in CNTS)

删除

要执行删除,您对元素的索引比它的存在更感兴趣。我能想到的最快方法是使用CNTS的元素作为比较键来遍历索引:

index = next((i for i, x in enumerate(CNTS) if (c == x).all()), -1)

此选项可以很好地短路,并返回-1作为默认索引,而不是引发StopIteration。如果您喜欢此错误,可以将参数-1删除到next。如果愿意,可以将(c == x).all()替换为np.array_equal(c, x)

现在您可以照常删除:

del CNTS[index]

答案 1 :(得分:2)

此解决方案适用于这种情况:

def arrayisin(array, list_of_arrays):
    for a in list_of_arrays:
        if np.array_equal(array, a):
            return True
    return False

此函数遍历数组列表并针对其他数组测试是否相等。因此用法是:

>>> arrayisin(c, CNTS)
True

要从列表中删除该数组,可以获取该数组的索引,然后使用list.pop。在函数get_index中,我们枚举数组列表,这意味着我们压缩列表的索引和列表的内容。如果有匹配项,我们将返回匹配项的索引。

def get_index(array, list_of_arrays):
    for j, a in enumerate(list_of_arrays):
        if np.array_equal(array, a):
            return j
    return None

idx = get_index(c, CNTS)  # 1
CNTS.pop(idx)

请参阅python数据结构教程,以获取list.pop https://docs.python.org/3/tutorial/datastructures.html

的文档

答案 2 :(得分:1)

使用System.Web.Optimization.BundleTable.EnableOptimizations = false删除要删除的列表的索引。

del