How to check if all items in a list are there in another list?

Be aware of the following:

>>>listA = ['a', 'a', 'b','b','b','c']
>>>listB = ['b', 'a','a','b','c','d']
>>>all(item in listB for item in listA)
True

If you read the "all" line as you would in English, This is not wrong but can be misleading, as listA has a third 'b' but listB does not.

This also has the same issue:

def list1InList2(list1, list2):
    for item in list1:
        if item not in list2:
            return False
    return True

Just a note. The following does not work:

>>>tupA = (1,2,3,4,5,6,7,8,9)
>>>tupB = (1,2,3,4,5,6,6,7,8,9)
>>>set(tupA) < set(TupB)
False

If you convert the tuples to lists it still does not work. I don't know why strings work but ints do not.

Works but has same issue of not keeping count of element occurances:

>>>set(tupA).issubset(set(tupB))
True

Using sets is not a comprehensive solution for multi-occurrance element matching.

But here is a one-liner solution/adaption to shantanoo's answer without try/except:

all(True if sequenceA.count(item) <= sequenceB.count(item) else False for item in sequenceA)

A builtin function wrapping a list comprehension using a ternary conditional operator. Python is awesome! Note that the "<=" should not be "==".

With this solution sequence A and B can be type tuple and list and other "sequences" with "count" methods. The elements in both sequences can be most types. I would not use this with dicts as it is now, hence the use "sequence" instead of "iterable".


A solution using Counter and the builtin intersection method (note that - is proper multiset difference, not an element-wise subtraction):

from collections import Counter

def is_subset(l1, l2):
    c1, c2 = Counter(l1), Counter(l2)
    return not c1 - c2

Test:

>>> List1 = ['a','c','c']
>>> List2 = ['x','b','a','x','c','y','c']
>>> is_subset(List1, List2)
True

When number of occurrences doesn't matter, you can still use the subset functionality, by creating a set on the fly:

>>> list1 = ['a', 'c', 'c']
>>> list2 = ['x', 'b', 'a', 'x', 'c', 'y', 'c']
>>> set(list1).issubset(list2)
True

If you need to check if each element shows up at least as many times in the second list as in the first list, you can make use of the Counter type and define your own subset relation:

>>> from collections import Counter
>>> def counterSubset(list1, list2):
        c1, c2 = Counter(list1), Counter(list2)
        for k, n in c1.items():
            if n > c2[k]:
                return False
        return True
   
>>> counterSubset(list1, list2)
True
>>> counterSubset(list1 + ['a'], list2)
False
>>> counterSubset(list1 + ['z'], list2)
False

If you already have counters (which might be a useful alternative to store your data anyway), you can also just write this as a single line:

>>> all(n <= c2[k] for k, n in c1.items())
True

Tags:

Python