比较字典列表

时间:2012-01-29 15:36:34

标签: python list dictionary

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

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;

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

任何帮助将不胜感激,

感谢。

3 个答案:

答案 0 :(得分:8)

试试这个:

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 :(得分:2)

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

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

代码看起来像这样:

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]

答案 2 :(得分:2)

要比较其键的子集上的两个词典d1d2,请使用:

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

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