简体   繁体   English

列表相交的旧方法:无集合且无in运算符

[英]Intersection of list in the old way: without sets and without in operator

As a python user, it is quite an unusual question. 作为python用户,这是一个不寻常的问题。 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. 我有2到6个包含自定义对象列表的列表。 The objects do have a method __eq__ but it is actually not correct for this usecase. 对象确实具有方法__eq__但实际上对于此用例而言是不正确的。 Moreover, they are loaded from a pickle file. 此外,它们是从pickle文件中加载的。 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. 如标题中所述,我正在所有其他列表中寻找L1元素。 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: 如何定义L1中的对象列表是否与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. 现在,此示例仅具有两个列表L1和L2。 What if I have L1, L2, L3, L4, L5 and L6 and I want the elements present in ALL of them? 如果我有L1,L2,L3,L4,L5和L6,并且我希望所有元素都存在该怎么办?

I'm currently trying using for loops, and an equality function: 我目前正在尝试使用for循环和一个相等函数:

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 : 您当然可以使用allany缩短它:

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. equality和交集中, all使用和any使用all保证了迭代的尽早中断。 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. 如果您发现第一个不匹配项时不知道elt.s的完整列表,则无需构建完整列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM