比较字典列表
我有两个测试结果的列表。这些测试结果用字典来表示:
list1 = [{testclass='classname', testname='testname', testtime='...},...]
list2 = [{testclass='classname', testname='testname', ...},...]
这两个列表中的字典表示方式稍微有点不同,因为其中一个列表包含更多的信息。不过在所有情况下,每个测试字典都会有一个classname和一个testname,这两个元素结合起来可以唯一识别这个测试,并且可以用来在两个列表之间进行比较。
我需要找出在列表1中但不在列表2中的所有测试,因为这些测试代表了新的失败。
为此,我这样做:
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风格的方法来实现这个。 我看过过滤器。过滤器使用的函数需要同时访问两个列表。一个列表很简单,但我不太确定怎么才能同时访问到两个列表。我知道列表的内容直到运行时才会确定。
任何帮助都将不胜感激,
谢谢。
3 个回答
2
如果每个 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]
2
要比较两个字典 d1
和 d2
中某些特定的键,可以使用:
all(d1[k] == d2[k] for k in ('testclass', 'testname'))
如果你的两个列表长度相同,可以使用 zip()
来把它们配对起来。
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]