Python intersection with object sets

I work with amazon boto and I have 2 lists. List 1 contains instance objects. List 2 contains InstanceInfo objects. Both objects have an attribute named id. I need to get a list of instance objects that id exists in the InstanceInfo list.

l1 = [Instance:i-04072534, Instance:i-06072536, Instance:i-08072538, Instance:i-0a07253a, Instance:i-e68fa1d6, Instance:i-e88fa1d8, Instance:i-ea8fa1da, Instance:i-ec8fa1dc] l2 = [InstanceInfo:i-ec8fa1dc, InstanceInfo:i-ea8fa1da, InstanceInfo:i-e88fa1d8, InstanceInfo:i-e68fa1d6] 

Required Result:

 l3 = [Instance:i-ec8fa1dc, Instance:i-ea8fa1da, Instance:i-e88fa1d8, Instance:i-e68fa1d6] 

Now I work through:

 l3= [] for a in l1 for b in l2: if a.id == b.id: l3.append(a) 

However, I was told that I should replace this using set intersection. I looked at examples, and it looks very simple. However, I do not see examples of working with objects.

I played a little, and theoretically I see how it works, but there may be some kind of β€œadvanced” syntax that I may not know. I am still learning python.

+4
source share
3 answers

Here is something faster than Marcin's answer (while similar):

 ids_l1 = set(x.id for x in l1) # All ids in list 1 intersection = [item for item in l2 if item.id in ids_l1] # Only those elements of l2 with an id in l1 

It is important to ids_l1 and not write if item.id in set(…) , since the set will be reconstructed every time (since the full test expression is reevaluated for each item element).

Python suites give you quick element ( in ) membership tests. Such tests are much faster with sets than with lists (since list items must be read one after another, while set items are "hashed").

+7
source

Your method may be relatively effective for small lists.

With sets, you will need to extract the identifiers, calculate the intersection of the identifiers, and then collect the elements into your new list. Sort of:

 set1 = set(x.id for x in l1) set2 = set(x.id for x in l2) intersection_ids = set1 & set2 intersection_list = [item for item in l2 if item.id in intersection_ids] 

You can make this a bit more efficient by looking at a shorter list or storing your objects in a dict.

-1
source

Try the following:

 # get ids of elements in second list l2_ids = [x.id for x in l2] # get elements from first list that have ids in second l3 = [x for x in l1 if x.id in l2_ids] 
-3
source

Source: https://habr.com/ru/post/1403891/


All Articles