两个列表之间的共同元素比较

2024-12-19 09:23:00
admin
原创
64
摘要:问题描述:给定两个输入列表,如何创建两个输入所共有元素的列表?例如:对于输入[1,2,3,4,5,6]和[3,5,7,9],结果应该是[3, 5];对于输入['this','this','n','that']和['this','not','that','that'],结果应该是['this', 'that']...

问题描述:

给定两个输入列表,如何创建两个输入所共有元素的列表?

例如:对于输入[1,2,3,4,5,6][3,5,7,9],结果应该是[3, 5];对于输入['this','this','n','that']['this','not','that','that'],结果应该是['this', 'that']


参见:

  • 在 Python 中,如何从两个列表中找到常用词同时保留词序?(保持顺序)

  • Python-多个列表的交集?(用于计算> ​​= 3个列表之间的交集)

  • 两个列表的交集包括重复项吗?(保留重复的元素)


解决方案 1:

使用 Python 的集合交集:

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

解决方案 2:

S.Mark和SilentGhost建议的解决方案通常会告诉您应该如何以 Pythonic 方式完成此操作,但我认为了解您的解决方案为何不起作用可能也会对您有所帮助。问题是,一旦您在两个列表中找到第一个公共元素,您只会返回该单个元素。您的解决方案可以通过创建一个result列表并收集该列表中的公共元素来解决:

def common_elements(list1, list2):
    result = []
    for element in list1:
        if element in list2:
            result.append(element)
    return result

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

def common_elements(list1, list2):
    return [element for element in list1 if element in list2]

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

解决方案 3:

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

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))

解决方案 4:

您可以使用以下方法解决这个问题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)

common_elements将是 numpy 数组:[3 5]

解决方案 5:

使用集合交集,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']
>>>
>>>

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

解决方案 6:

设置是解决这个问题的另一种方法

a = [3,2,4]
b = [2,3,5]
set(a)&set(b)
{2, 3}

解决方案 7:

我比较了每个答案提到的每种方法。目前,我使用 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)))

如果您运行此代码,您会发现,如果您使用列表或生成器(如果您迭代生成器,而不仅仅是使用它。当我强制生成器打印其长度时,我这样做了),您将获得几乎相同的性能。但是如果您使用集合,您将获得更好的性能。此外,如果您使用交集方法,您将获得更好的性能。我的电脑中每种方法的结果如下所列:

  1. 方法1:0.8150673999999999974619413478649221360683441

  2. 方法2:0.8329545000000001531148541289439890533685684

  3. 方法3:0.0016547000000000089414697868051007390022277

  4. 方法4:0.001026299999999244948867271887138485908508

解决方案 8:

前面的答案都适用于查找唯一的公共元素,但无法解释列表中的重复项。如果您希望公共元素以与列表中相同的数量出现,则可以使用以下一行代码:

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

or True仅当您希望任何元素的计算结果为 时,该部分才是必要的False

解决方案 9:

1)方法 1 保存 list1 为字典,然后迭代 list2 中的每个元素

def findarrayhash(a,b):
    h1={k:1 for k in a}
    for val in b:
        if val in h1:
            print("common found",val)
            del h1[val]
        else:
            print("different found",val)
    for key in h1.iterkeys():
        print ("different found",key)

寻找共同点和不同点:

2)方法2使用set

def findarrayset(a,b):
    common = set(a)&set(b)
    diff=set(a)^set(b)
    print list(common)
    print list(diff) 

解决方案 10:

这里有一些在 O(l1+l2) 中执行但不计算重复项的解决方案,还有一些考虑重复项的慢速解决方案(至少是 O(l1*l2),但可能更昂贵)。

所以我认为我应该添加一个 O(l1log(l1)+l2(log(l2)) 解决方案。如果列表已经排序,这尤其有用。

def common_elems_with_repeats(first_list, second_list):
    first_list = sorted(first_list)
    second_list = sorted(second_list)
    marker_first = 0
    marker_second = 0
    common = []
    while marker_first < len(first_list) and marker_second < len(second_list):
        if(first_list[marker_first] == second_list[marker_second]):
            common.append(first_list[marker_first])
            marker_first +=1
            marker_second +=1
        elif first_list[marker_first] > second_list[marker_second]:
            marker_second += 1
        else:
            marker_first += 1
    return common

另一个更快的解决方案是,从 list1 创建一个 item->count 映射,然后迭代 list2,同时更新映射并计算重复项。不需要排序。需要额外的一点内存,但从技术上讲是 O(l1+l2)。

解决方案 11:

如果 list1 和 list2 未排序:

使用交集:

print((set(list1)).intersection(set(list2)))

合并列表并检查元素的出现次数是否多于 1:

combined_list = list1 + list2
set([num for num in combined_list if combined_list.count(num) > 1])

与上面类似,但不使用设置:

for num in combined_list:
    if combined_list.count(num) > 1:
        print(num)
        combined_list.remove(num)

对于排序列表,没有 python 特殊内置函数,O(n) 解决方案

p1 = 0
p2 = 0
result = []
while p1 < len(list1) and p2 < len(list2):
    if list1[p1] == list2[p2]:
        result.append(list1[p1])
        p1 += 1
        p2 += 2
    elif list1[p1] > list2[p2]:
        p2 += 1
    else:
        p1 += 1
print(result)

解决方案 12:

如果您不需要同时获得整个输出,则可以使用生成器,实际上它会更快:

common = (x for x in list1 if x in list2)

这里的优点是,即使使用巨大的列表或其他巨大的可迭代对象,它也会在恒定时间内(几乎即时)返回生成器。

例如,

list1 =  list(range(0,10000000))
list2=list(range(1000,20000000))
common = (x for x in list1 if x in list2)

使用 list1 和 list2 的这些值来回答这里的所有其他问题都需要很长时间。

然后你可以用以下方法迭代答案

for i in common: print(i)

解决方案 13:

我已经制定了深度交叉的完整解决方案

def common_items_dict(d1, d2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
    result = {}
    if use_set_for_dict_key_commons:
        shared_keys=list(set(d1.keys()).intersection(d2.keys())) # faster, order not preserved
    else:
        shared_keys=common_items_list(d1.keys(), d2.keys(), use_set_for_list_commons=False)

    for k in  shared_keys:
        v1 = d1[k]
        v2 = d2[k]
        if isinstance(v1, dict) and isinstance(v2, dict):
            result_dict=common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
            if len(result_dict)>0 or append_empty:
                result[k] = result_dict 
        elif isinstance(v1, list) and isinstance(v2, list):
            result_list=common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
            if len(result_list)>0 or append_empty:
                result[k] = result_list 
        elif v1 == v2:
            result[k] = v1
    return result

def common_items_list(d1, d2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
    if use_set_for_list_commons: 
        result_list= list(set(d2).intersection(d1)) # faster, order not preserved, support only simple data types in list values
        return result_list

    result = []
    for v1 in d1: 
        for v2 in d2:
            if isinstance(v1, dict) and isinstance(v2, dict):
                result_dict=common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
                if len(result_dict)>0 or append_empty:
                    result.append(result_dict)
            elif isinstance(v1, list) and isinstance(v2, list):
                result_list=common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
                if len(result_list)>0 or append_empty:
                    result.append(result_list)
            elif v1 == v2:
                result.append(v1)
    return result


def deep_commons(v1,v2, use_set_for_list_commons=True, use_set_for_dict_key_commons=True, append_empty=False):
    """
    deep_commons
     returns intersection of items of dict and list combinations recursively

    this function is a starter function, 
    i.e. if you know that the initial input is always dict then you can use common_items_dict directly
    or if it is a list you can use common_items_list directly

    v1 - dict/list/simple_value
    v2 - dict/list/simple_value
    use_set_for_dict_key_commons - bool - using set is faster, dict key order is not preserved 
    use_set_for_list_commons - bool - using set is faster, list values order not preserved, support only simple data types in list values
    append_empty - bool - if there is a common key, but no common items in value of key , if True it keeps the key with an empty list of dict

    """

    if isinstance(v1, dict) and isinstance(v2, dict):
        return common_items_dict(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
    elif isinstance(v1, list) and isinstance(v2, list):
        return common_items_list(v1, v2, use_set_for_list_commons, use_set_for_dict_key_commons, append_empty)
    elif v1 == v2:
        return v1
    else:
        return None


needed_services={'group1':['item1','item2'],'group3':['item1','item2']}
needed_services2={'group1':['item1','item2'],'group3':['item1','item2']}

result=deep_commons(needed_services,needed_services2)

print(result)

解决方案 14:

list1=[123,324523,5432,311,23]
list2=[2343254,34234,234,322123,123,234,23]
common=[]
def common_elements(list1,list2):
    for x in range(0,len(list1)):
        if list1[x] in list2:
            common.append(list1[x])
            
common_elements(list1,list2)
print(common)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   990  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   26  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   27  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   26  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   53  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用