在Python中找出2个清单之间的差异

Ath*_*dom 3 python python-2.7

通过比较对象的属性之一,如何找到对象的2个字典之间的差异?

在此示例中,如果两个对象的phone属性相同,则称它们彼此相等。

a1 = {'name':'Tom', 'phone':'1234'}
a2 = {'name':'Dick', 'phone':'1111'}
a3 = {'name':'Harry', 'phone':'3333'}
a = [a1,a2,a3]

b1 = {'name':'Jane', 'phone':'1234'}
b2 = {'name':'Liz', 'phone':'2222'}
b3 = {'name':'Mary', 'phone':'4444'}
b = [b1,b2,b3]

def check(x, y):
    if(x['phone'] == y['phone']):
        return True
    else:
        return False
Run Code Online (Sandbox Code Playgroud)

理想的结果应该是:

result_A_minus_B = [a2, a3]
result_B_minus_A = [b2, b3]
Run Code Online (Sandbox Code Playgroud)

我在下面的尝试引发错误 TypeError: list indices must be integers, not str

[x for x in a if check(a,b)]
Run Code Online (Sandbox Code Playgroud)

Pet*_*per 5

使用给定的数据结构,您将不得不反复遍历第二个词典列表中的项目,这效率相对较低。您只关心第二个词典列表中是否已经存在给定的电话号码。重复测试是否存在给定值的最有效数据结构是set(或dict如果您可能需要从电话号码索引回更多信息)。因此,我将按以下方式进行操作:

a = [a1, a2, a3]
b = [b1, b2, b3]
a_phone_numbers_set = set(d['phone'] for d in a])
b_phone_numbers_set = set(d['phone'] for d in b])
result_A_minus_B = [d for d in a if d['phone'] not in b_phone_numbers_set]
result_B_minus_A = [d for d in b if d['phone'] not in a_phone_numbers_set]
Run Code Online (Sandbox Code Playgroud)

或者,如果我想创建一个函数:

def unmatched_entries(list1, list2):
    existing_entries = set(d['phone'] for d in list2)
    return [d for d in list1 if d['phone'] not in existing_entries]
Run Code Online (Sandbox Code Playgroud)

(可选)您可以使用任意键:

def unmatched_entries(list1, list2, matching_key):
    existing_entries = set(d[matching_key] for d in list2 if matching_key in d)
    return [d for d in list1 if matching_key in d and d[matching_key] not in existing_entries]
Run Code Online (Sandbox Code Playgroud)

该版本始终跳过list1中未定义请求键的条目-可能会发生其他行为。

为了匹配短暂出现的注释所暗示的多个键,我将使用一组值的元组:

a_match_elements = set((d['phone'], d['email']) for d in a])
result_B_minus_a = [d for d in b if (d['phone'], d['email']) not in a_match_elements]
Run Code Online (Sandbox Code Playgroud)

同样,可以将其概括为处理一系列键。