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

How can I compare two lists in python and return matches

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

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

returnMatches(a, b)

例如,会返回[5]


不是最有效的方法,但到目前为止最明显的方法是:

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

如果顺序很重要,您可以使用如下列表理解来完成:

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

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


使用set.intersection(),它快速且可读。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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)

以下是我机器上的结果:

1
2
3
4
5
6
7
8
9
# 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()的答案至少和其他解决方案一样快,而且也是最易读的,所以它应该是解决这个常见问题的标准解决方案。


我喜欢固定答案,但这里有一个无论如何都有效的答案

1
[x for x in a if x in b]

最简单的方法是使用集合:

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

1
2
3
4
5
6
7
8
9
10
>>> 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'])**


快速方式:

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

另外,您可以通过在新列表中保留公共元素来尝试此操作。

1
2
3
4
new_list = []
for element in a:
    if element in b:
        new_list.append(element)

你想要副本吗?如果不是,也许你应该用集合代替:

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


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

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

也可以使用itertools.product。

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


你可以使用:

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

输出:

1
set([1, 7, 9])


你可以使用

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

1
2
3
4
5
6
7
8
9
10
11
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


如果需要布尔值:

1
2
3
4
5
6
7
8
>>> 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

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

1
2
3
4
5
6
7
8
9
10
11
12
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]


我只是使用了以下方法,它对我很有用:

1
2
3
4
5
6
7
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个。不过,可能表现不太好。


使用__and__属性方法也可以。

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

或者简单地

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.