合并两个列表并删除重复项,但不要删除原始列表中的重复项。

176
我有两个列表,需要将它们合并在一起,如果第二个列表中有任何与第一个列表重复的元素,则忽略这些元素。有点难以解释,因此让我展示一下代码的样子,以及我想得到的结果。
first_list = [1, 2, 2, 5]

second_list = [2, 5, 7, 9]

# The result of combining the two lists should result in this list:
resulting_list = [1, 2, 2, 5, 7, 9]
你会注意到结果包含第一个列表,包括其中的两个"2"值,但第二个列表多出来的2和5的值没有被添加到第一个列表中。通常像这样的问题我会使用集合,但对第一个列表使用集合会清除它已经有的重复值。所以我想知道实现这种组合的最佳/最快方法是什么。谢谢。

4
如果second_list中有三个2会怎样? - balpha
@balpha:是的,我还没有完全决定如何处理那个问题。虽然我已经考虑过这个问题,但由于我对此事还没有决定,所以将其排除了 :) - Lee Olayvar
12个回答

236
你需要将第二个列表中不在第一个列表中的元素添加到第一个列表中 - 集合是确定这些元素最简单的方法,像这样:
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

in_first = set(first_list)
in_second = set(second_list)

in_second_but_not_in_first = in_second - in_first

result = first_list + list(in_second_but_not_in_first)
print(result)  # Prints [1, 2, 2, 5, 9, 7]

或者如果你更喜欢一行代码 8-)

print(first_list + list(set(second_list) - set(first_list)))

2
如果你需要排序,可以使用以下代码:print first_list + sorted(set(second_list) - set(first_list)) - hughdbrown
3
List(set(first_list)|set(second_list)) # | 表示集合的并集,参见 https://dev59.com/im445IYBdhLWcg3w1tmi - staticd
1
@staticd:是的,但那会得到错误的答案。你的结果中只有一个“2”,但实际上应该有两个。 - RichieHindle
哎呀,你说得对。我完全忽略了第一个列表允许重复项。:P - staticd
请注意:此解决方案不保留顺序。要使用该功能,请访问 https://dev59.com/2HM_5IYBdhLWcg3wlEFH#1319355 。 - Dr_Zaszuś

128
resulting_list = list(first_list)
resulting_list.extend(x for x in second_list if x not in resulting_list)

18
终于有一个不需要转换为集合的答案了!赞一个。 - SuperFamousGuy
4
实际上这是O(n*m)的,但在你有一个非可哈希对象列表且性能不是问题时会很方便。 - alcuadrado
2
我不希望有任何重复的内容,无论是第一组还是第二组。 - Dejell
7
这种技术保留了属性列表中的顺序,而使用“set”则不然。 - Subhash

74

你可以使用集合:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

resultList= list(set(first_list) | set(second_list))

print(resultList)
# Results in : resultList = [1,2,5,7,9]

好的,谢谢。这个可以正常工作。resultList = first_list + list(set(second_list) - set(first_list)) - Kathiravan Umaidurai

30
first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

print( set( first_list + second_list ) )

16
你可以使用numpy将此代码缩减为一行:
a = [1,2,3,4,5,6,7]
b = [2,4,7,8,9,10,11,12]

sorted(np.unique(a+b))

>>> [1,2,3,4,5,6,7,8,9,10,11,12]

12

对我来说,最简单的是:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

merged_list = list(set(first_list+second_list))
print(merged_list)

#prints [1, 2, 5, 7, 9]

1
这是一个很好的解决方案,但请记住,如果我们尝试将字典数组转换为集合,它将无法工作,例如(会引发“TypeError:不可哈希类型:'dict'”) - Evgenia Karunus

8
resulting_list = first_list + [i for i in second_list if i not in first_list]

1
对 first_list 进行去重并“设置”。 - u0b34a0f6ae
生成的列表不会被排序。 - avakar
1
如果我也不希望任何列表有重复,该怎么办?这样,如果一个列表有重复,它们将返回。 - Dejell

4

您还可以将RichieHindle和Ned Batchelder的回答结合起来,得到一个平均情况时间复杂度为O(m+n)的算法,同时保持顺序:

first_list = [1, 2, 2, 5]
second_list = [2, 5, 7, 9]

fs = set(first_list)
resulting_list = first_list + [x for x in second_list if x not in fs]

assert(resulting_list == [1, 2, 2, 5, 7, 9])

请注意,x in s 的最坏情况复杂度为 O(m),因此该代码的最坏情况复杂度仍为 O(m*n)

2

您可以使用 dict.fromkeys 返回一个没有重复项的列表:

def mergeTwoListNoDuplicates(list1, list2):
    """
    Merges two lists together without duplicates
    :param list1:
    :param list2:
    :return:
    """
    merged_list = list1 + list2
    merged_list = list(dict.fromkeys(merged_list))
    return merged_list

1
我喜欢这个 [*dict.fromkeys(list1+list2)] 公式,而且经常使用它。 - KCharlie

1

基于食谱

resulting_list = list(set().union(first_list, second_list))

意思是将两个列表合并去重,生成一个新的列表。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接