简体   繁体   English

Pythonic方法按属性比较两个无序列表

[英]Pythonic Way to compare two unordered lists by attributes

what is the most pythonic way to compare two unordered lists by one or more of their attributes? 通过一个或多个属性比较两个无序列表的最pythonic方法是什么? I would love to know if there is a pythonic way to find out if for each item in a list A there exists an item in list B where the item from list A and the item in list B match in a specified attribute. 我想知道是否有一种pythonic方法来查明列表A中的每个项目是否存在列表B中的项目,其中列表A中的项目和列表B中的项目在指定属性中匹配。

In my example case, I have two .zip files in a unit test, and want to test, if the files match, but I am really looking for a good general solution for my personal toolset. 在我的示例中,我在单元测试中有两个.zip文件,并且想要测试,如果文件匹配,但我真的在为我的个人工具集寻找一个很好的通用解决方案。 This was my first attempt: 这是我的第一次尝试:

with ZipFile('A.zip') as old:
with ZipFile('B.zip') as new:
oldFileInfo = old.infolist()

allFound = True
for info in new.infolist():
   matches = [item for item in oldFileInfo if item.CRC == info.CRC and \   
              basename(item.filename) == basename(info.filename) ]
   if len(matches) == 0:
       allFound = False
       break

Maybe it is trivial, but I have not yet found a nice way how to do it. 也许这是微不足道的,但我还没有找到一个很好的方法来做到这一点。

Greetings Michael 问候迈克尔

It is easy, you should use sets: 这很简单,你应该使用套装:

if set(list1).difference(set(list2)):
    # lists are different
    # different_items = set(list1).difference(set(list2))
    pass
else:
    # lists are the same
    pass

You can convert your structure to iterables or lists: 您可以将结构转换为iterables或lists:

list1 = [(i.CRC, basename(i.filename)) for i in old.infolist()]
list2 = [(i.CRC, basename(i.filename)) for i in new.infolist()]

One possible way to do it can be: 一种可能的方法是:

def areEqual(old, new):
    set1 = set((x.attribute1, x.attribute2) for x in old)
    set2 = set((x.attribute1, x.attribute2) for x in new)

    return set1 == set2

You can create sets out of old and new lists and then compare them: 您可以使用旧列表和新列表创建集合,然后比较它们:

old_set = set((item.CRC, item.filename) for item in old_info)
new_set = set((item.CRC, item.filename) for item in new_info)

all_match = new_set.issubset(old_set)  # or old_set.issuperset(new_set)

You can start by sorting the lists. 您可以从排序列表开始。 It has only a bigO of n log n and then you can just compare the elements one by one and stop if you find a pair that does not match. 它只有n log n的bigO然后你可以逐个比较元素,如果找到一对不匹配则停止。

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

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