【问题标题】:How to compare 2 lists and remove duplicates from 1 efficiently? [duplicate]如何有效地比较 2 个列表并从 1 中删除重复项? [复制]
【发布时间】:2020-01-29 19:48:39
【问题描述】:

我需要比较 2 个列表并有效地从第二个数组中删除出现在第一个数组中的元素。我的解决方案如下:

自制算法

#function accepts 2 arrays. Compares elements from 1st array to 2nd to see if they exist in 2nd, 
#and removes them from 2nd array. 
def compareRemove(self, array1 = [], array2 = []):

    #starting iteration values
    i = 0
    j = 0

    array1_length = len(array1)
    array2_length = len(array2)

    while i < array1_length:
        while j < array2_length:

            #compare element from first array to second array, remove element if same, 
            #and update second array length
            if array1[i] == array2[j]:

                del array2[j]
                array2_length = len(array2)

            #otherwise move j forward
            else:
                j = j + 1

        #when 2nd while loop is done move i forward and reset j to 0
        i = i + 1
        j = 0

    return array2

对 SO 的研究建议:

updated_file_strings = [x for x in array2 if not x in array1]

两者都同样快,但是随着我的阵列长度增加,两者都会变慢。即使数组长度增加,我是否可以使用任何可以很好地执行的方法?顺序无关紧要。

示例:

array1 = [1, 2, 3] array2 = [1, 2, 3, 5, 5, 5]

result_array = [5, 5, 5]

删除第二个数组中的重复项。

【问题讨论】:

  • 请创建一个最小的、可验证的示例和您的预期输出,以便我们更好地帮助您

标签: python


【解决方案1】:

转换为set,删除元素,然后转换回list

s1 = set(array1)
s2 = set(array2)
array2 = list(s2.difference(s1))

编辑:要跟踪重复项,您可以使用 collections.Counter 并重建列表。

from collections import Counter

s1 = set(array1)
array2 = [x for x in array2 if x not in s1]
# d2 = Counter(array2)
# array2 = [z for k, v in d2.items() if k not in s1 for z in [k] * v]

EDIT2:我认为使用Counter 会更快,但理解中的二级列表构造似乎抵消了任何收益。最好只创建第一个 set,然后使用它进行存在性检查。

测试:Counter 和双重理解

%%timeit
array1 = [random.randint(0, 10000) for _ in range(200000)]
array2 = [random.randint(0, 20000) for _ in range(200000)]
s1 = set(array1)
d2 = Counter(array2)
[z for k, v in d2.items() if k not in s1 for z in [k]*v]

# returns:
525 ms ± 19.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

测试:带有存在性检查的单一理解

%%timeit
array1 = [random.randint(0, 10000) for _ in range(200000)]
array2 = [random.randint(0, 20000) for _ in range(200000)]
s1 = set(array1)
#d2 = Counter(array2)
[x for x in array1 if x not in s1]

# returns:
510 ms ± 17.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

  • 我不能,因为 set 会从 array2 中删除任何重复项。我需要他们计算频率。这就是为什么我比较只删除两个数组中存在的相同元素的原因。不应删除 array2 中存在的欺骗。
  • 查看更新。
  • 谢谢詹姆斯,这很有帮助。不知道为什么我的问题被关闭了,它远不及丹尼尔建议的重复。可能甚至没有读过这个问题......
猜你喜欢
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2020-12-14
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多