527

I want to take two lists and find the values that appear in both.

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

returnMatches(a, b)

would return [5], for instance.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
tehryan
  • 24,405
  • 11
  • 28
  • 17
  • 7
    The answers below all seem wrong to me. What happens if a number is repeated in either list, surely you'd want to know that (?) (eg., say both lists have '5' twice) Any solution using sets will immediately remove all repeated items and you'll lose that info. – M.H. Mar 25 '19 at 00:32
  • The question was interpreted in two different ways. If the goal is to find all the elements that are common to both lists (regardless of where they appear in the list), that is a list intersection. Otherwise, if the goal is to compare each pair of elements in the corresponding positions, then we simply iterate pairwise and check each pair. Either way, there are better versions of the question, so I closed this with the two different duplicate links. – Karl Knechtel Oct 03 '22 at 21:00
  • If want to return columns that are not in another df (also applicable to list), numpy solutions are here as jezrael's answer. https://stackoverflow.com/questions/43028969/pandas-return-columns-in-dataframe-that-are-not-in-other-dataframe/43029056#43029056 – DOT Dec 30 '22 at 21:04

21 Answers21

681

Not the most efficient one, but by far the most obvious way to do it is:

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

if order is significant you can do it with list comprehensions like this:

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

(only works for equal-sized lists, which order-significance implies).

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
  • 26
    A note of caution, the list comprehension is *not* necessarily the faster option. For larger sets (where performance is most likely to matter) the bitwise comparison (`&`) or `set(a).intersection(b)` will be as fast or faster than list comprehension. – Joshmaker Jun 03 '12 at 17:00
  • 38
    Another note of caution: the list comprehension finds the values that appear in both at the SAME positions (this is what SilentGhost meant by "order is significant"). The set intersection solutions will also find matches at DIFFERENT positions. These are answers to 2 quite different questions... (the op's question is ambiguous as to which it is asking) – drevicko Nov 24 '13 at 22:58
  • 1
    How do you do this if your lists are lists of lists i.e. a = [[0,0], [1,0]] and b = [[2,3],[0,0]] – Schneems Mar 12 '17 at 21:18
  • 4
    What would be the time complexity of the first example ```set(a) & set(b)``` ? – AdjunctProfessorFalcon May 19 '17 at 01:56
  • Note, this does not work if both sets are empty and you expect comparison to pass. So change to "(set(a) and set(b)) or (not a and not b)" – Goblinhack Oct 02 '19 at 19:40
  • @AdjunctProfessorFalcon The time complexity is `O(n + m)` if the size of the lists is `n` and `m` respectively. – dionyziz Dec 17 '19 at 17:23
  • 2
    how do you find items that are, for example, in list A, but not in list B? – oldboy May 23 '21 at 22:42
557

Use set.intersection(), it's fast and readable.

>>> set(a).intersection(b)
set([5])
Dennis
  • 56,821
  • 26
  • 143
  • 139
  • 36
    This answer has good algorithmic performance, as only one of the lists (shorter should be preferred) is turned into a set for quick lookup, and the other list is traversed looking up its items in the set. – u0b34a0f6ae Sep 07 '09 at 12:08
  • 32
    `bool(set(a).intersection(b))` for `True` or `False` – Akshay Oct 20 '17 at 03:20
  • 10
    This answer is more flexible and readable, since people may need [`difference`](https://docs.python.org/3/library/stdtypes.html#frozenset.difference) or [`union`](https://docs.python.org/3/library/stdtypes.html#frozenset.union). – Shihe Zhang Nov 01 '17 at 02:31
  • What if I have objects as list elements and only want partial matches, i.e., only some attributes have to match for it to be considered as matching object? – stefanbschneider Mar 22 '18 at 20:39
  • 1
    Is there any performance difference for `.intersection()` vs `&`? – brandonbanks Aug 07 '19 at 13:57
  • @brandonbanks See Joshmaker's answer – Jonathan Lam Aug 07 '19 at 21:05
  • @u0b34a0f6ae why should the shorter one specifically be turned into a set? wouldn't there also be a performance increase in keeping the shorter as the list, as it would reduce the number of iterations? – Josh Katofsky Nov 05 '19 at 23:57
138

A quick performance test showing Lutz's solution is the best:

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)

These are the results on my machine:

# 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

Obviously, any artificial performance test should be taken with a grain of salt, but since the set().intersection() answer is at least as fast as the other solutions, and also the most readable, it should be the standard solution for this common problem.

Parth
  • 1,114
  • 3
  • 16
  • 25
Joshmaker
  • 4,068
  • 3
  • 27
  • 29
  • Set is actually removing repetitions, so in my case wont work – rgralma Mar 06 '20 at 08:23
  • @rgralma making a new `set` from an existing `list` won't remove anything from the original `list`. If you want special logic to handle duplicates within a list, I think you'll need to ask a new question because the answer will need to be specific to how you want duplicates to be handled. – Joshmaker Mar 25 '20 at 17:11
88

I prefer the set based answers, but here's one that works anyway

[x for x in a if x in b]
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
29

Quick way:

list(set(a).intersection(set(b)))
DisplacedAussie
  • 4,578
  • 1
  • 27
  • 21
23

The easiest way to do that is to use sets:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
set([5])
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
17
>>> 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'])**
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
setz
  • 171
  • 1
  • 3
17

Also you can try this,by keeping common elements in a new list.

new_list = []
for element in a:
    if element in b:
        new_list.append(element)
mushfiq
  • 1,602
  • 2
  • 19
  • 35
  • I actually really like this answer, it's the most readable to me and would be good for beginners, especially when handling smaller datasets. :) – Myexgiko Dec 06 '22 at 17:21
13

Do you want duplicates? If not maybe you should use sets instead:

>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])
Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Timothy Pratley
  • 10,586
  • 3
  • 34
  • 63
  • If you really want lists, http://www.java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5] – Timothy Pratley Sep 07 '09 at 11:16
  • According to the doc - *... precludes error-prone constructions like Set('abc') & 'cbs' in favor of the more readable Set('abc').intersection('cbs').* - http://docs.python.org/library/sets.html – Aaron Newton May 31 '12 at 13:40
11

another a bit more functional way to check list equality for list 1 (lst1) and list 2 (lst2) where objects have depth one and which keeps the order is:

all(i == j for i, j in zip(lst1, lst2))   
itmatters
  • 665
  • 6
  • 8
6

Can use itertools.product too.

>>> common_elements=[]
>>> for i in list(itertools.product(a,b)):
...     if i[0] == i[1]:
...         common_elements.append(i[0])
SuperNova
  • 25,512
  • 7
  • 93
  • 64
5

One more way to find common values:

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
matches = [i for i in a if i in b]
Pavel Botsman
  • 773
  • 1
  • 11
  • 25
4

You can use

def returnMatches(a,b):
       return list(set(a) & set(b))
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Prabhu
  • 3,434
  • 8
  • 40
  • 48
4

You can use:

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

Output:

set([1, 7, 9])
Adnan Ghaffar
  • 1,345
  • 7
  • 26
  • 46
3

If you want a boolean value:

>>> 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
Matheus Araujo
  • 5,551
  • 2
  • 22
  • 23
3
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 
Harish Verma
  • 548
  • 7
  • 17
  • 1
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Jul 20 '17 at 00:45
1

Using __and__ attribute method also works.

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

or simply

>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>    
SuperNova
  • 25,512
  • 7
  • 93
  • 64
1

The following solution works for any order of list items and also supports both lists to be different length.

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]
Hafizur Rahman
  • 2,314
  • 21
  • 29
0
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.
ravi tanwar
  • 598
  • 5
  • 16
  • 4
    The question was for list and no set. use of the `&` operator on set is already answer by SilentGhost in the accepted answer – dWinder Jul 18 '18 at 19:34
0

I just used the following and it worked for me:

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)

this would then print 5 in your case. Probably not great performance wise though.

Elarbe
  • 95
  • 9
0

This is for someone who might what to return a certain string or output, here is the code, hope it helps:

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()
derek
  • 21
  • 7