[python] Common elements comparison between 2 lists

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)

Got that so far, but can't seem to get it to work!

Any ideas?

This question is related to python list

The answer is


Set is another way we can solve this

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

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

I know 3 ways can solve this, Of course, there could be more.

1-

common_elements = [e for e in list1 if e in list2]

2-

import numpy as np
common_elements = np.intersect1d(list1, list2)

3-

common_elements = set(list1).intersection(list2)

The 3rd way is the fastest because Sets are implemented using hash tables.


this is my proposition i think its easier with sets than with a for loop

def unique_common_items(list1, list2):
   # Produce the set of *unique* common items in two lists.
   return list(set(list1) & set(list2))

you can use a simple list comprehension:

x=[1,2,3,4]
y=[3,4,5]
common = [i for i in x if i in y]
common: [3,4]

You can also use sets and get the commonalities in one line: subtract the set containing the differences from one of the sets.

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

Just use list comprehension.

Half line solution:

common_elements = [x for x in list1 if x in list2]

If that helped, consider upvoting my answer.


The previous answers all work to find the unique common elements, but will fail to account for repeated items in the lists. If you want the common elements to appear in the same number as they are found in common on the lists, you can use the following one-liner:

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

The or True part is only necessary if you expect any elements to evaluate to False.


There are solutions here that do it in O(l1+l2) that don't count repeating items, and slow solutions (at least O(l1*l2), but probably more expensive) that do consider repeating items.

So I figured I should add an O(l1log(l1)+l2(log(l2)) solution. This is particularly useful if the lists are already sorted.

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

Another faster solution would include making a item->count map from list1, and iterating through list2, while updating the map and counting dups. Wouldn't require sorting. Would require extra a bit extra memory but it's technically O(l1+l2).


The solutions suggested by S.Mark and SilentGhost generally tell you how it should be done in a Pythonic way, but I thought you might also benefit from knowing why your solution doesn't work. The problem is that as soon as you find the first common element in the two lists, you return that single element only. Your solution could be fixed by creating a result list and collecting the common elements in that list:

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

An even shorter version using list comprehensions:

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

However, as I said, this is a very inefficient way of doing this -- Python's built-in set types are way more efficient as they are implemented in C internally.


I compared each of method that each answer mentioned. At this moment I use python 3.6.3 for this implementation. This is the code that I have used:

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)))

If you run this code you can see that if you use list or generator(if you iterate over generator, not just use it. I did this when I forced generator to print length of it), you get nearly same performance. But if you use set you get much better performance. Also if you use intersection method you will get a little bit better performance. the result of each method in my computer is listed bellow:

  1. method1: 0.8150673999999999974619413478649221360683441
  2. method2: 0.8329545000000001531148541289439890533685684
  3. method3: 0.0016547000000000089414697868051007390022277
  4. method4: 0.0010262999999999244948867271887138485908508

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

1) Method1 saving list1 is dictionary and then iterating each elem in 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)

Finding Common and Different elements:

2) Method2 using set

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

Use a generator:

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

The advantage here is that this will return in constant time (nearly instant) even when using huge lists or other huge iterables.

For example,

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

All other answers here will take a very long time with these values for list1 and list2.

You can then iterate the answer with

for i in common: print(i)

Or convert it to a list with

list(i)

use set intersections, 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']
>>>
>>>

Note that result list could be different order with original list.