Reputation: 479
I'm looking for a clean way to check if an item is member of a list of objects. Basically this is what I want to do:
class Constant:
def __init__(self,name,value):
self.name = name
self.value = value
list = [Constant('el1',1),Constant('el2',2)]
list2= ['el4','el5','el1']
for item in list2:
#clean solution for this if clause is needed (I'm aware list.name triggers an error)
if item in list.name:
print 'it is a member'
So it is important to me that the item matches only on the name, the value has no meaning when searching. I know I can solve this by adding an additional for loop like this:
for item in list2:
for itemConstant in list:
if item == itemConstant.name:
print 'it is a member'
But I want to be sure there is no better solution than this.
Upvotes: 1
Views: 1562
Reputation: 180391
Since the value has no meaning use a set with in
as strings are hashable and you will have a 0(1)
lookups, storing the names from the instances in a set:
st = {Constant('el1',1).name,Constant('el2',2).name}
lst2 = ['el4','el5','el1']
for c in lst2:
if c in st:
print('it is a member')
Or make lst2 a set:
lst = [Constant('el1',1), Constant('el2',2)]
st = {'el4','el5','el1'}
for c in lst:
if c.name in st:
print(c.name)
I presume you want exact matches as "foo" in "foobar"
would be True.
You can also leave the original list as is an create a set from the instance names:
lst = [Constant('el1', 1), Constant('el2', 2)]
lst2 = ['el4', 'el5', 'el1']
st = {c.name for c in lst}
for c in lst2:
if c in st:
print('it is a member')
So you still have an 0(n) solution as it just requires one more pass over your instances lst.
Upvotes: 1
Reputation: 1121386
Make list2
a set and loop over your list of constants to test each against that set. Use the any()
callable to exit early when a match is found:
constants = [Constant('el1', 1), Constant('el2',2)]
elements = {'el4', 'el5', 'el1'}
if any(c.name in elements for c in constants):
print 'is a member'
This reduces the problem to one loop; membership testing against a set is a O(1) constant time operation on average. The loop is exited early when a match is found, further reducing the number of tests made.
Upvotes: 0
Reputation: 42748
You can use any
:
for item in list2:
if any(item == c.name for c in list):
print 'it is a member'
Upvotes: 4