快速检查列表中重复数组的方法

时间:2018-09-05 23:50:58

标签: python arrays python-3.x numpy

我有一个列表(我们叫它all_my_arrays)包含大约48,000个1D数组。我想知道此列表中有多少个重复数组(如果有)。但是,我想排除空数组(因为列表中有多个空数组,并且不希望将这些空数组计入我的重复计数中)。我在下面尝试了此代码,但是花费的时间太长:

import numpy as np
uniques=[]
for arr in all_my_arrays:
    if not np.array_equal(np.array([]), arr):
        if not any(np.array_equal(arr, unique_arr) for unique_arr in uniques):
           uniques.append(arr)
print(len(uniques)) #number of non-duplicates

是否有更快的方法来完成此操作?

4 个答案:

答案 0 :(得分:1)

您可以使用set类型来获取列表中的唯一值。首先,您必须将数组转换为可哈希的类型(这里的元组很好)。这是一个示例:

uniques = set(tuple(arr) for arr in all_my_arrays if arr.size > 0)

集合uniques将包含原始all_my_arrays列表中的所有唯一的非空数组。 uniques的内容是元组,但是您可以使用列表理解将它们转换回数组。如果您仅对唯一数组的数量感兴趣,则可以调用len(uniques),而不必担心转换回数组。

此方法的时间复杂度为O(n + m),其中n是数组的数目,m是数组的长度。但是,转换为元组会产生开销,但是我认为这种方法应该比您目前使用的方法(具有时间复杂性O(n^2))要快得多,尤其是对于如此大量的数组。

编辑:要使其更快一点,可以删除每个元素上的空支票,然后在末尾对其进行处理。如下所示:

uniques = set(tuple(arr) for arr in all_my_arrays)
num_unique = len(uniques) if () not in uniques else len(uniques) - 1

答案 1 :(得分:0)

这是一个基于NumPy的解决方案,可能对您有用。为简单起见,我将使用一个数组长度为3或0的示例。

请注意,按照您的定义,重复计数等于数组总数空数组的数目唯一非空数组的数目。

最后一部分可能是最昂贵的,但是我们可以在常规NumPy数组上使用np.unique

L = [np.array([1, 2, 3]), np.array([]), np.array([3, 2, 1]),
     np.array([1, 3, 2]), np.array([1, 2, 3]), np.array([1, 3, 2]),
     np.array([]), np.array([]), np.array([1, 2, 3])]

empty_arr = {idx for idx, arr in enumerate(L) if arr.shape == (0,)}
empty_count = len(empty_arr)

A = np.array([arr for idx, arr in enumerate(L) if idx not in empty_arr])

unique_arr = np.unique(A, axis=0)

duplicates = len(L) - len(empty_arr) - len(unique_arr)

print(duplicates)  # 3

答案 2 :(得分:0)

我不确定自己是否完全了解您的问题。

不过,据我了解:

  1. 您有一个包含7个元素numpy数组的Python列表;
  2. 您要过滤掉全部为0的数组;
  3. 然后,您想要获得剩余物品的唯一计数。

如果正确,则可以执行以下操作:

import numpy as np
li_of_arr=[np.random.choice(4,7) for _ in range(50000)] # example list of arrays
mat=np.array([e for e in li_of_arr if np.any(e)])   # create a numpy matrix of non zero arrays
uniq=np.unique(mat,axis=0)    # here are your unique sub arrays
print (len(mat), len(uniq))   # len of non zero elements and unique non zero elements

这在我的MacBook上花费不到1秒。

答案 3 :(得分:0)

只需

in_arr = np.array([i for i in all_my_arrays if i.size == 7])
uniques = np.unique(in_arr, axis = 0)
uniques_list = list(uniques)  # if you really want a list

编辑:请注意np.unique在内部进行排序,因此不会保留顺序。如果您想维持订单,则可能需要构建特殊的numba函数。