检查两个列表中是否有任何公共元素:Python

时间:2020-07-29 16:34:01

标签: python python-3.x

所以我正在研究这个简单的程序,以检查两个列表中是否有共同的元素 因此我编写的代码使用了if嵌套,但我想知道有没有比嵌套格式更好的方法呢?

def common_data(list1, list2):
     result = False
     for x in list1:
         for y in list2:
             if x == y:
                 result = True
                 return result

还有没有办法检查n个列表中的公共元素?

3 个答案:

答案 0 :(得分:3)

您可以使用any遍历一个列表,然后检查另一个列表中的包含。这样的好处是在找到第一个包含的元素时会发生短路。

>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> any(i in b for i in a)
True

或者,您可以检查两个列表之间的set.intersection的大小

>>> a = [1,2,3,4]
>>> b = [4,5,6,7]
>>> len(set(a).intersection(b)) > 0
True

答案 1 :(得分:1)

第一个选项最简单。您想知道列表2中是否有列表1中的任何元素。生成器理解力几乎可以将英语概念直接转化为代码。对于大型列表而言,这种方法效率低下,但是编码起来非常容易。

result = any(x in list2 for x in list1)

如果您的元素是可哈希的,则可以通过将集合用于O(1)包含查找来改进它。请注意,我们只想从最小的列表中创建一个集合,以最大程度地减少额外的内存并为该操作工作,并且我们使用内置的any()使其短路并在我们立即找到一个list2中的项目。

if len(list1) > len(list2):
    list1, list2 = list2, list1
cache = set(list1)
result = any(x in cache for x in list2)

如果您的元素不可散列且不可排序,另一种选择是对两个列表进行排序,合并并检查重复项(至关重要的是,这是一个与您的相等性定义相匹配的完整顺序-当元素不同时,一个应该小于另一个)。

值得注意的是,由于所有其他元组,这具有相当高的对象创建开销。可能需要编写自己的例程来逐步浏览两个排序的列表,并跟踪上一个元素来自哪个列表,而不是调用heapq.merge()

import heapq

list1, list2, prev, result = sorted(list1), sorted(list2), None, False
for item, i in heapq.merge(
        ((x, 1) for x in list1),
        ((x, 2) for x in list2)):
    if prev and item==prev[0] and i!=prev[1]:
        result = True
        break
    prev = (item, i)

还可能值得注意的是,如果您唯一可用的操作是相等性测试(对象不可排序,不可哈希等),则通常无法将len(list1)的最坏情况提高到O(nm)以上)== n和len(list2)== m。仍然有一个有趣的特殊情况(例如,如果唯一元素的数量很少),但是如果您没有有关该问题的其他信息,那么您将比天真的解决方案做得更好。

答案 2 :(得分:1)

如果元素是可哈希的...

更短的表情

>>> list1 = [1, 2, 3]
>>> list2 =    [2, 3, 4]
>>> bool(set(list1) & set(list2))
True

对于您的“ n个列表”问题:

>>> lists = [[1, 2, 3, 4, 5],
                [2, 3, 4, 5, 6],
                   [3, 4, 5, 6, 7],
                      [4, 5, 6, 7, 8]]
>>> bool(set(lists[0]).intersection(*lists))
True

当然,如果您只是打算在bool之类的布尔上下文中使用它,或者如果您确实想了解公共元素,则可能不需要显式转换为if ... :

>>> if set(list1) & set(list2):
        print('common!')

common!

>>> set(list1) & set(list2)
{2, 3}

>>> set(lists[0]).intersection(*lists)
{4, 5}