2个列表之间的常见元素比较

Dan*_*iel 109 python list

def common_elements(list1, list2):
    """
    Return a list containing the elements which are in both list1 and list2

    >>> common_elements([1,2,3,4,5,6], [3,5,7,9])
    [3, 5]
    >>> common_elements(['this','this','n','that'],['this','not','that','that'])
    ['this', 'that']
    """
    for element in list1:
        if element in list2:
            return list(element)
Run Code Online (Sandbox Code Playgroud)

到目前为止,但似乎无法让它工作!

有任何想法吗?

Sil*_*ost 215

>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]
Run Code Online (Sandbox Code Playgroud)

  • 这将返回/ unique/common元素,但不返回可能存在的任何重复元素. (13认同)
  • 供参考。这绝对比 Tamás 提出的解决方案更快,但是对于我在此页面上结束时正在查看的用例,重要的是保留后过滤元素的元素的原始顺序。这种方法失去了顺序,而列表理解方法保留了顺序。如果有人需要考虑这一点,这很重要。谢谢。 (3认同)

小智 39

您还可以使用集合并在一行中获取共性:从包含其中一个集合的差异中减去包含该集合的集合.

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))
Run Code Online (Sandbox Code Playgroud)

  • 这会将A转换为两次,不必要地浪费。 (2认同)

jrr*_*eda 35

您可以使用numpy以下方法解决此问题:

import numpy as np

list1 = [1, 2, 3, 4, 5, 6]
list2 = [3, 5, 7, 9]

common_elements = np.intersect1d(list1, list2)
print(common_elements)
Run Code Online (Sandbox Code Playgroud)

common_elements将是 numpy 数组:[3 5]


Tam*_*más 31

所建议的解决方案S.MarkSilentGhost通常告诉你应该如何在一个Python化的方式来完成,但我认为从知道为什么你的解决方案不工作,你也可能受益.问题是,只要找到两个列表中的第一个公共元素,就只返回该单个元素.您可以通过创建result列表并收集该列表中的公共元素来修复您的解决方案:

def common_elements(list1, list2):
    result = []
    for element in list1:
        if element in list2:
            result.append(element)
    return result
Run Code Online (Sandbox Code Playgroud)

使用列表推导的更短版本:

def common_elements(list1, list2):
    return [element for element in list1 if element in list2]
Run Code Online (Sandbox Code Playgroud)

但是,正如我所说,这是一种非常低效的方法 - Python的内置集类型更有效,因为它们在C内部实现.

  • 注意:上述方法仅适用于相同大小的列表。如果您像我一样使用大小不等的列表,那么您需要在调用函数之前根据 len() 评估顺序:list1 = [2,2,2], list2[2,3] -> [2,2,2] 列表 1 = [2,3], 列表 2[2,2,2] -> [2] (2认同)

YOU*_*YOU 26

使用set intersectionctions,set(list1)&set(list2)

>>> def common_elements(list1, list2):
...     return list(set(list1) & set(list2))
...
>>>
>>> common_elements([1,2,3,4,5,6], [3,5,7,9])
[3, 5]
>>>
>>> common_elements(['this','this','n','that'],['this','not','that','that'])
['this', 'that']
>>>
>>>
Run Code Online (Sandbox Code Playgroud)

请注意,结果列表可能与原始列表的顺序不同.

  • 好的解决方案 还有一种方法可以保存订单吗? (4认同)

Mah*_*chi 11

你可以使用一个简单的列表理解:

x=[1,2,3,4]
y=[3,4,5]
common = [i for i in x if i in y]
common: [3,4]
Run Code Online (Sandbox Code Playgroud)


Sab*_*oki 8

我比较了每个答案提到的每种方法。目前我使用 python 3.6.3 来实现。这是我使用的代码:

import time
import random
from decimal import Decimal


def method1():
    common_elements = [x for x in li1_temp if x in li2_temp]
     print(len(common_elements))


def method2():
    common_elements = (x for x in li1_temp if x in li2_temp)
    print(len(list(common_elements)))


def method3():
    common_elements = set(li1_temp) & set(li2_temp)
    print(len(common_elements))


def method4():
    common_elements = set(li1_temp).intersection(li2_temp)
    print(len(common_elements))


if __name__ == "__main__":
    li1 = []
    li2 = []
    for i in range(100000):
        li1.append(random.randint(0, 10000))
        li2.append(random.randint(0, 10000))

    li1_temp = list(set(li1))
    li2_temp = list(set(li2))

    methods = [method1, method2, method3, method4]
    for m in methods:
        start = time.perf_counter()
        m()
        end = time.perf_counter()
        print(Decimal((end - start)))
Run Code Online (Sandbox Code Playgroud)

如果您运行此代码,您可以看到,如果您使用列表或生成器(如果您迭代生成器,而不仅仅是使用它。当我强制生成器打印它的长度时,我这样做了),您将获得几乎相同的性能。但是如果你使用 set 你会得到更好的性能。此外,如果您使用相交方法,您将获得更好的性能。下面列出了我计算机中每种方法的结果:

  1. 方法1:0.8150673999999999974619413478649221360683441
  2. 方法2:0.8329545000000001531148541289439890533685684
  3. 方法3:0.0016547000000000089414697868051007390022277
  4. 方法4:0.0010262999999999244948867271887138485908508


Dol*_*gan 6

之前的答案都可以找到唯一的共同元素,但无法解释列表中重复的项目.如果您希望公共元素显示在列表中常见的相同数字上,则可以使用以下单行:

l2, common = l2[:], [ e for e in l1 if e in l2 and (l2.pop(l2.index(e)) or True)]
Run Code Online (Sandbox Code Playgroud)

or True只有在您期望评估任何元素时,才需要该部分False.

  • 该解决方案的运行时间至少为 O(len(l1)*len(l2)) (不考虑 pop 和索引 (e) 的成本) (3认同)
  • 在列表理解中使用可变(有副作用)语句不是一个好习惯。除了这是低效的,[this other answer](/sf/answers/4580160511/) 在可维护性和运行时间方面都更好。 (2认同)

nEO*_*nEO 5

设置是我们可以解决此问题的另一种方法

a = [3,2,4]
b = [2,3,5]
set(a)&set(b)
{2, 3}
Run Code Online (Sandbox Code Playgroud)

  • 您还可以将此解决方案构建到 list() 中以输出为列表:`list(set(a)&set(b))` (2认同)