Home > Python > Find out if every element of a list is part of another, with Python

Find out if every element of a list is part of another, with Python

August 26th, 2010 Leave a comment Go to comments

Update 2010-08-27: Comments indicated that what I did here is not the best solution. Like noted in my original post, a set would be better in this case. I eventually used set(r).issubset(set(l)). Marius also pointed out to set(r) <= set(l), but I like the issubset one more.

I wanted to check if every element of one list or tuple is part of another one using Python. A set has the issubset()-method, but I couldn't find anything build-in for a tuple. It was, however, rather quickly done:

>>> r = (1,2)
>>> l = (3,4,1,5,2)
>>> False not in [ e in l for e in r ]
True
>>> r = (1,9)
>>> False not in [ e in l for e in r ]
False

Why I'm posting this? I just found it cute code, somehow.

Tags: , ,
  1. kaizer.se
    August 26th, 2010 at 23:51 | #1

    Instead of `False not in …` you should use `all(e in l for e in r)` the buddies all(..) and any(..) are pretty neat for this.

  2. Marius Gedminas
    August 27th, 2010 at 00:32 | #2

    Do you really find that clearer than set(r) <= set(l)?

  3. matt harrison
    August 27th, 2010 at 03:38 | #3

    This is probably implied in Marius' response, but using a set brings the running time to O(m+n) rather than the O(m*n) found in your solution.

  4. Geert JM Vanderkelen
    August 27th, 2010 at 06:46 | #4

    Ah, I just found it sexy, late-night code, and yes, there are much better, more performant solutions. :)
    I did eventually use sets.

  5. Masklinn
    August 27th, 2010 at 11:12 | #5

    Geert, you don't have to set() the parameter to set.issubset, it can take any iterable (as opposed to the "equivalent" operator which mandates both operands to be sets):

    >>> set(range(3, 6)).issubset(range(10))
    True
    >>> set(range(3, 6)) <= range(10)
    Traceback (most recent call last):
    File "", line 1, in
    TypeError: can only compare to a set
    >>> set(range(3, 6)) <= set(range(10))
    True

    > This is probably implied in Marius' response, but using a set brings the running time to O(m+n) rather than the O(m*n) found in your solution.

    But building a Python set is rather more expensive than building a list (or even a bunch of lists). In the case this piece of code is in a tight loop and a hot spot, doing for the manual check can be less expensive.

    That's after measuring naturally, the default should be set operations (though I'm not fond of using infix operators apart from & and |, I generally find the method calls much clearer)

  1. No trackbacks yet.