As a python user, it is quite an unusual question. For once, I can not use all the magic functions and lovely build-in operators. Thus I am kind of lost.
I have 2 to 6 lists containing lists of custom objects. The objects do have a method __eq__
but it is actually not correct for this usecase. Moreover, they are loaded from a pickle file. Thus, I can not modify the object class and re-implement the method.
L1 = [[Obj1_1, Obj1_2, Obj1_3], [Obj2_1, Obj2_2, Obj2_3], ...]
L2 = [[Obj1_12, Obj1_21, Obj1_33], [Obj2_1, Obj2_2, Obj2_3], ...]
...
As stated in the title, I'm looking for the element of L1 presents in all the other lists. ie I'm looking for the sublist of objects present in the other lists of sublists.
How to I define if a list of object from L1 is the same as a list of object from L2:
List_of_Obj_in_L1 == List_of_Obj_in_L12 and [elt.s for elt in List_of_Obj_in_L1] == [elt.s for elt in List_of_Obj_in_L2]
Knowing those lists are quite large (thousands of elements), how can I find the intersection based on this condition?
Dummy example:
class Dummy:
def __init__(self, f, s):
self.f = f
self.s = s
def __eq__(self, D):
return self.f == D.f
def __ne__(self, D):
return not self.__eq__(self, D)
L1 = [[Dummy(f, 0) for f in (20, 30, 20, 50)], [Dummy(f, 0) for f in (20, 30, 20, 40)], [Dummy(f, k) for k, f in enumerate((20, 30, 20, 50))], [Dummy(f, 10) for f in (20, 50)]]
L2 = [[Dummy(f, 0) for f in (20, 20, 20, 50)], [Dummy(f, 0) for f in (10, 10, 10, 10)], [Dummy(f, k) for k, f in enumerate((20, 30, 20, 50))], [Dummy(f, 10) for f in (20, 50)]]
The intersection would be those 2 lists:
Intersect = [[Dummy(f, k) for k, f in enumerate((20, 30, 20, 50))], [Dummy(f, 0) for f in (20, 50)]]
Now this example has only 2 lists, L1 and L2. What if I have L1, L2, L3, L4, L5 and L6 and I want the elements present in ALL of them?
I'm currently trying using for loops, and an equality function:
def equality(L_dummy1, L_dummy2):
if L_dummy1 == L_dummy2 and [elt.s for elt in L.dummy1] == [elt.s for elt in L.dummy2]:
return True
else:
return False
intersection = list()
for elt in L1:
in_L2 = False
for elt2 in L2:
if equality(elt, elt2):
in_L2 = True
in_L3 = False
for elt2 in L3:
if equality(elt, elt2):
in_L3 = True
if in_L2 and in_L3:
intersection.append(elt)
Any better way to do this? Thanks!
You can certainly shorten it, using all
and any
:
def equality(L_dummy1, L_dummy2):
return L_dummy1 == L_dummy2 and \
all(elt1.s==elt2.s for elt1, elt2 in zip(L.dummy1, L.dummy2))
intersection = [
elt for elt in L1 if all(any(equality(elt, x) for x in l) for l in (L2, L3))
]
In both the equality
and the intersection the use of all
and any
guarantees early breaking of the iterations. There is no need to build the full lists of elt.s
if you know they are not equal when you see the first mismatch.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.