如何比较python中的两个列表并返回匹配项

Posted

技术标签:

【中文标题】如何比较python中的两个列表并返回匹配项【英文标题】:How can I compare two lists in python and return matches 【发布时间】:2010-11-26 04:56:20 【问题描述】:

我想获取两个列表并找到两个列表中出现的值。

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

returnMatches(a, b)

例如会返回[5]

【问题讨论】:

下面的答案对我来说似乎都是错误的。如果一个数字在任一列表中重复会发生什么,您肯定想知道 (?)(例如,说两个列表都有两次“5”)任何使用集合的解决方案都会立即删除所有重复的项目,你会输那个信息。 How to find list intersection?的可能重复 【参考方案1】:

不是最有效的方法,但迄今为止最明显的方法是:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
5

如果顺序很重要,您可以使用这样的列表推导来做到这一点:

>>> [i for i, j in zip(a, b) if i == j]
[5]

(仅适用于大小相等的列表,这意味着顺序重要性)。

【讨论】:

请注意,列表理解不一定是更快的选择。对于较大的集合(性能最重要),按位比较 (&) 或 set(a).intersection(b) 将与列表理解一样快或更快。 另一个注意事项:列表推导式查找出现在两个相同位置的值(这就是 SilentGhost 的“顺序很重要”的意思)。设置的交叉点解决方案还将在不同的位置找到匹配项。这些是对 2 个完全不同的问题的答案......(操作员的问题对于它所问的问题是模棱两可的) 如果您的列表是列表列表,即 a = [[0,0], [1,0]] 和 b = [[2,3],[0,0 ]] 第一个例子set(a) & set(b)的时间复杂度是多少? 您如何找到例如在列表 A 中但不在列表 B 中的项目?【参考方案2】:

使用set.intersection(),它既快速又易读。

>>> set(a).intersection(b)
set([5])

【讨论】:

这个答案有很好的算法性能,因为只有一个列表(应该更短)被变成一个快速查找的集合,另一个列表被遍历查找它在集合中的项目。 bool(set(a).intersection(b)) for TrueFalse 这个答案更加灵活易读,因为人们可能需要differenceunion 如果我有对象作为列表元素并且只想要部分匹配,即只有一些属性必须匹配才能被视为匹配对象? .intersection()& 的性能有何不同?【参考方案3】:

显示 Lutz 解决方案的快速性能测试是最好的:

import time

def speed_test(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        for x in xrange(5000):
            results = func(*args, **kwargs)
        t2 = time.time()
        print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
        return results
    return wrapper

@speed_test
def compare_bitwise(x, y):
    set_x = frozenset(x)
    set_y = frozenset(y)
    return set_x & set_y

@speed_test
def compare_listcomp(x, y):
    return [i for i, j in zip(x, y) if i == j]

@speed_test
def compare_intersect(x, y):
    return frozenset(x).intersection(y)

# Comparing short lists
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

# Comparing longer lists
import random
a = random.sample(xrange(100000), 10000)
b = random.sample(xrange(100000), 10000)
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

这些是我机器上的结果:

# Short list:
compare_bitwise took 10.145 ms
compare_listcomp took 11.157 ms
compare_intersect took 7.461 ms

# Long list:
compare_bitwise took 11203.709 ms
compare_listcomp took 17361.736 ms
compare_intersect took 6833.768 ms

显然,任何人为的性能测试都应该慎重考虑,但由于set().intersection() 的答案至少与其他解决方案一样快,而且可读性最强,因此它应该成为这个常见问题的标准解决方案。

【讨论】:

Set 实际上是在删除重复,所以在我的情况下不会工作 @rgralma 从现有的list 中创建一个新的set 不会从原始list 中删除任何内容。如果您需要特殊逻辑来处理列表中的重复项,我认为您需要提出一个新问题,因为答案需要具体说明您希望如何处理重复项。【参考方案4】:

我更喜欢基于集合的答案,但这是一个无论如何都有效的答案

[x for x in a if x in b]

【讨论】:

【参考方案5】:

快捷方式:

list(set(a).intersection(set(b)))

【讨论】:

【参考方案6】:

最简单的方法是使用sets:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
set([5])

【讨论】:

【参考方案7】:
>>> s = ['a','b','c']   
>>> f = ['a','b','d','c']  
>>> ss= set(s)  
>>> fs =set(f)  
>>> print ss.intersection(fs)   
   **set(['a', 'c', 'b'])**  
>>> print ss.union(fs)        
   **set(['a', 'c', 'b', 'd'])**  
>>> print ss.union(fs)  - ss.intersection(fs)   
   **set(['d'])**

【讨论】:

接受的答案不适用于包含字符串的列表。这个可以。【参考方案8】:

您也可以尝试这样做,方法是将常用元素保留在新列表中。

new_list = []
for element in a:
    if element in b:
        new_list.append(element)

【讨论】:

【参考方案9】:

另一种更实用的方法来检查列表 1 (lst1) 和列表 2 (lst2) 的列表相等性,其中对象的深度为 1 并且保持顺序是:

all(i == j for i, j in zip(lst1, lst2))   

【讨论】:

【参考方案10】:

你想要重复吗?如果不是,也许您应该改用集合:

>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])

【讨论】:

如果你真的想要列表,java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5] 根据文档 - ... 排除了容易出错的结构,如 Set('abc') & 'cbs' 支持更具可读性的 Set('abc').intersection( 'cbs')。 - docs.python.org/library/sets.html【参考方案11】:

也可以使用 itertools.product。

>>> common_elements=[]
>>> for i in list(itertools.product(a,b)):
...     if i[0] == i[1]:
...         common_elements.append(i[0])

【讨论】:

【参考方案12】:

你可以使用

def returnMatches(a,b):
       return list(set(a) & set(b))

【讨论】:

【参考方案13】:

你可以使用:

a = [1, 3, 4, 5, 9, 6, 7, 8]
b = [1, 7, 0, 9]
same_values = set(a) & set(b)
print same_values

输出:

set([1, 7, 9])

【讨论】:

这与 6 多年前接受的答案有何不同? 好吧,我用输出写了完整的细节,对初学者 python 有好处【参考方案14】:

如果你想要一个布尔值:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
False
>>> a = [3,1,2]
>>> b = [1,2,3]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
True

【讨论】:

【参考方案15】:
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

lista =set(a)
listb =set(b)   
print listb.intersection(lista)   
returnMatches = set(['5']) #output 

print " ".join(str(return) for return in returnMatches ) # remove the set()   

 5        #final output 

【讨论】:

虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。【参考方案16】:

使用__and__属性方法也可以。

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a).__and__(set(b))
set([5])

或者干脆

>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>    

【讨论】:

【参考方案17】:

以下解决方案适用于任何顺序的列表项,并且还支持两个列表的长度不同。

import numpy as np
def getMatches(a, b):
    matches = []
    unique_a = np.unique(a)
    unique_b = np.unique(b)
    for a in unique_a:
        for b in unique_b:
            if a == b:
                matches.append(a)
    return matches
print(getMatches([1, 2, 3, 4, 5], [9, 8, 7, 6, 5, 9])) # displays [5]
print(getMatches([1, 2, 3], [3, 4, 5, 1])) # displays [1, 3]

【讨论】:

Numpy 有一个特定的功能:np.intersect1d(list1, list2)【参考方案18】:

我刚刚使用了以下内容,它对我有用:

group1 = [1, 2, 3, 4, 5]
group2 = [9, 8, 7, 6, 5]

for k in group1:
    for v in group2:
        if k == v:
            print(k)

这将在您的情况下打印 5 。不过,性能可能不是很好。

【讨论】:

【参考方案19】:
you can | for set union and & for set intersection.
for example:

    set1=1,2,3
    set2=3,4,5
    print(set1&set2)
    output=3

    set1=1,2,3
    set2=3,4,5
    print(set1|set2)
    output=1,2,3,4,5

curly braces in the answer.

【讨论】:

问题是列表而不是集合。在片场使用& 运算符已经是 SilentGhost 在接受的答案中的答案【参考方案20】:

这适用于可能返回某个字符串或输出的人, 这是代码,希望对您有所帮助:

lis =[]
#convert to list
a = list(data)
b = list(data)
def make_list():
    c = "greater than"
    d = "less_than"
    e = "equal"
    for first, first_te in zip(a, b):
        if first < first_te:
            lis.append(d)
        elif first > first_te:
            lis.append(c)
        else:
            lis.append(e)
    return lis

make_list()

【讨论】:

【参考方案21】:

另一种找到共同值的方法:

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
matches = [i for i in a if i in b]

【讨论】:

以上是关于如何比较python中的两个列表并返回匹配项的主要内容,如果未能解决你的问题,请参考以下文章

Python:在元组列表和嵌套列表中比较并查找匹配项

PHP:如何将一个数组中的键与另一个数组中的值进行比较,并返回匹配项?

比较python中的列表值

如何编写从两个搜索值返回匹配项的 sql 查询

比较两个列表并使用 linq 返回不匹配的项目

如何映射两个数组并将匹配项作为按钮返回?