【问题标题】:Comparing lists of dictionaries比较字典列表
【发布时间】:2012-02-21 16:27:49
【问题描述】:

我有两个测试结果列表。测试结果表示为字典:

list1 = [{testclass='classname', testname='testname', testtime='...},...]
list2 = [{testclass='classname', testname='testname', ...},...]

两个列表中的字典表示略有不同,因为对于一个列表,我有一些 更多信息。但在所有情况下,任一列表中的每个测试字典都会有一个 classname 和 testname 元素,它们共同有效地形成了一种唯一标识测试的方法以及一种在列表之间进行比较的方法。

我需要找出所有在 list1 中但不在 list2 中的测试,因为它们代表新的测试失败。

我这样做:

def get_new_failures(list1, list2):
    new_failures = []
    for test1 in list1:
        for test2 in list2:
            if test1['classname'] == test2['classname'] and \
                    test1['testname'] == test2['testname']:
                break; # Not new breakout of inner loop
        # Doesn't match anything must be new
        new_failures.append(test1);
    return new_failures;

我想知道这是一种更 Python 的方式。我看了过滤器。过滤器使用的函数需要获得两个列表的句柄。一个很容易,但我不确定如何处理这两个问题。我确实知道列表的内容,直到运行时。

任何帮助将不胜感激,

谢谢。

【问题讨论】:

    标签: python list dictionary


    【解决方案1】:

    如果classname 和testname 的每个组合确实是唯一的,那么计算效率更高的方法是使用两个字典而不是两个列表。作为字典的键,使用这样的元组:(classname, testname)。然后你可以简单地说if (classname, testname) in d: ...。

    如果您需要保留插入顺序,并且使用的是 Python 2.7 或更高版本,则可以使用 collections 模块中的 OrderedDict。

    代码如下所示:

    tests1 = {('classname', 'testname'):{'testclass':'classname', 
                                         'testname':'testname',...}, 
             ...}
    tests2 = {('classname', 'testname'):{'testclass':'classname', 
                                         'testname':'testname',...}, 
             ...}
    
    new_failures = [t for t in tests1 if t not in tests2]
    

    如果您出于某种原因必须使用列表,您可以遍历 list2 以生成一个集合,然后测试该集合中的成员资格:

    test1_tuples = ((d['classname'], d['testname']) for d in test1)
    test2_tuples = set((d['classname'], d['testname']) for d in test2)
    new_failures = [t for t in test1_tuples if t not in test2_tuples]
    

    【讨论】:

    • 您的代码运行良好,但在 test2_tuples = ... 行中有错字 - 缺少括号
    【解决方案2】:

    要比较两个字典 d1 和 d2 在其键的子集上,请使用:

    all(d1[k] == d2[k] for k in ('testclass', 'testname'))
    

    如果您的两个列表长度相同,您可以使用zip() 将它们配对。

    【讨论】:

    • @senderle:如果他有两个列表,我看不出有什么问题。
    【解决方案3】:

    试试这个:

    def get_new_failures(list1, list2):
        check = set([(d['classname'], d['testname']) for d in list2])
        return [d for d in list1 if (d['classname'], d['testname']) not in check]
    

    【讨论】:

    • +1,这是我的下一个想法——我没有注意到你已经发布了它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 2017-08-21
    • 2023-01-07
    • 2021-06-24
    • 1970-01-01
    相关资源
    最近更新 更多