Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check item membership in set in Python

Tags:

python

set

Hello I've been coding for a couple of months now and know the basics, but I'm having a set membership problem for which I can't find a solution.

I have a list of lists of pairs of integers, and I want to remove the list that have the "a" integer in them. I thought using sets was the easiest way. Bellow is the code:

## This is the item to test against. 
a = set([3]) 
## This is the list to test.      
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]     

## This is a list that will contain the lists present
## in groups which do not contain "a"
groups_no_a = []        

for group in groups:
    group = set(group)
    if a in group:
        groups_no_a.append(group)
    ## I thought the problem had something to do with
    ## clearing the variable so I put this in,   
    ## but to no remedy. 
    group.clear()  


print groups_no_a 

I had also tried using s.issubset(t) until I realized that this tested if every element in s in t.

Thank you!

like image 847
grasshopper Avatar asked Aug 18 '13 15:08

grasshopper


2 Answers

You want to test if there is no intersection:

if not a & group:

or

if not a.intersection(group):

or, inversely, that the sets are disjoint:

if a.isdisjoint(group):

The method forms take any iterable, you don't even have to turn group into a set for that. The following one-liner would work too:

groups_no_a = [group for group in groups if a.isdisjoint(group)]

Demo:

>>> a = set([3]) 
>>> groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]     
>>> [group for group in groups if a.isdisjoint(group)]
[[1, 2], [5, 4]]

If all you are testing for is one element, then it could be that creating sets is going to cost more in performance than what you gain in testing for membership, and just doing:

3 not in group

where group is a short list.

You can use the timeit module to compare pieces of Python code to see what works best for your specific typical list sizes.

like image 119
Martijn Pieters Avatar answered Oct 12 '22 17:10

Martijn Pieters


Maybe you could use List Comprehension:

a = 3
groups = [[3, 2], [3, 4], [1, 2], [5, 4], [4, 3]]
print [x for x in groups if a not in x]

Edit based on a comment:

Well to those curious, what I want to do is; I have a list like the following: [ [error, [ [group_item_1, group_item_2], [...], [...], [...] ] ], [more like this previous], [...] ], and I want to get the item with least error and that doesn't have "a" in group_item_1 or group_item_2. The lists are already sorted by error. I sorta almost go it :D

This should do the trick:

from itertools import chain, iterfilter

def flatten(listOfLists):
    "Flatten one level of nesting"
    return chain.from_iterable(listOfLists)


errors_list =  [ ['error0', [ [30, 2], [3, 4], [1, 2], [5, 4], [4, 3] ] ], ['error1', [ [31, 2], [3, 4], [1, 2], [5, 4], [4, 3] ] ] ]

a = 30
result = next(ifilter(lambda err: a not in flatten(err[1]), reversed(errors_list)), None)

print result #finds error1 as it has no 30 on its list
like image 38
lpiepiora Avatar answered Oct 12 '22 16:10

lpiepiora