2

Possible Duplicate:
Common elements comparison between 2 lists

I have two Lists:

[Apples, Bananas, Pears]
[Kiwis, Bananas, Apples]

I would like to get only the elements that both lists share. There have to be some built-in functions in python for that.

Result:

[Apples, Bananas]
Community
  • 1
  • 1
tarrasch
  • 2,630
  • 8
  • 37
  • 61

2 Answers2

12
>>> set(["Apples", "Bananas", "Pears"]).intersection(["Kiwis", "Bananas", "Apples"])
set(['Bananas', 'Apples'])
>>> list(_)
['Bananas', 'Apples']

Which is equivalent to:

>>>set(["Apples", "Bananas", "Pears"]) & set(["Kiwis", "Bananas", "Apples"])
set(['Bananas', 'Apples'])
AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173
Alexey Kachayev
  • 6,106
  • 27
  • 24
10

Original Answer:

[x for x in list1 if x in list2]

In response to the comment question about preserving order:

That list comprehension is just a shorthand version of

intersection = []
for x in list1:
    if x in list2: #Note that using 'in' involves looping over list2
        intersection.append(x)

With this expanded version, it's a little easier to see what is going on. The output list is exactly list1 with the elements that are in list2 removed. So it will preserve the order of list1. For example, if list1 = [1,2,3] and list2 = [3,2,5], the output of the list comprehension will be [2,3]. If the position of the lists was reversed like this

[x for x in list2 if x in list1]

Then the order of list2 would be preserved in the output, giving us [3,2].

Also, in a possibly undesirable side effect, this means that this method will contain duplicate elements of list1. For example:

>>> [x for x in [1,2,3,3,3] if x in [2,3]]
[2, 3, 3, 3]

So for your example, this happens:

>>> [fruit for fruit in ["Apples", "Bananas", "Pears"] if fruit in ["Kiwis", "Bananas", "Apples"]]
['Apples', 'Bananas']

But if the lists are flipped, then the output is reversed:

>>> [fruit for fruit in ["Kiwis", "Bananas", "Apples"] if fruit in ["Apples", "Bananas", "Pears"]]
['Bananas', 'Apples']

So, in general, the sets solution is better because it is more efficient and because often you won't want the duplicate elements. However, if you want to preserve order, this is the way to go. (If you want to preserve order and not have duplicates, you can just use this method and then strip out the duplicates, depending on whether you want the earlier duplicate or a later one to remain.)

Matthew Adams
  • 9,426
  • 3
  • 27
  • 43
  • this construct is new to me, still it is much more upvoted. Can you explain this a bit more, for me? – tarrasch Aug 30 '12 at 15:05
  • It's a list comprehension that filters the elements of the final list by checking if they're in list2. – Jake Biesinger Aug 30 '12 at 15:07
  • Check out the documentation: http://docs.python.org/tutorial/datastructures.html#list-comprehensions – Matthew Adams Aug 30 '12 at 15:09
  • Be careful with list comprehensions - they're very powerful, but are much more prone to being hard to read and therefore debug. – rsegal Aug 30 '12 at 15:13
  • 2
    It's not particularly efficient though. It's probably fine for small input lists (in fact it would probably even perform better than other solutions under a certain threshold since there's no hashing or sorting overhead), but you are, worst case, iterating all of list2 for every element of list1. – Silas Ray Aug 30 '12 at 15:14
  • 3
    Performance note: This looks like a single loop, but it's actually two. The `in` operator needs to loop over elements in `list2` for each element in `list1`. If the lists are large, this can become an expensive operation. (If `list2` were a set, testing for membership would be less computationally expensive.) – Steven Rumbalski Aug 30 '12 at 15:15
  • These people speak truth- I'm +1ing the other answer. – Matthew Adams Aug 30 '12 at 15:16
  • actually, does this preserve order? i can't really get it to work for me, but i am trying. the other solution works, but destroys order. – tarrasch Aug 30 '12 at 16:35
  • @tarrasch Hopefully that edit helps. – Matthew Adams Aug 30 '12 at 17:04