Сравнение 2 списков, состоящих из словарей с уникальными ключами в Python - PullRequest
26 голосов
/ 23 марта 2012

У меня есть 2 списка, каждый из которых содержит одинаковое количество словарей. Каждый словарь имеет уникальный ключ. Существует соответствие для каждого словаря первого списка во втором списке, то есть словарь с уникальным ключом существует в другом списке. Но другие элементы таких 2 словарей могут отличаться. Например:

list_1 = [
            {
                'unique_id': '001',
                'key1': 'AAA',
                'key2': 'BBB',
                'key3': 'EEE'
             },
             {
                'unique_id': '002',
                'key1': 'AAA',
                'key2': 'CCC',
                'key3': 'FFF'
             }
         ]

 list_2 = [
             {
                'unique_id': '001',
                'key1': 'AAA',
                'key2': 'DDD',
                'key3': 'EEE'
             },
             {
                'unique_id': '002',
                'key1': 'AAA',
                'key2': 'CCC',
                'key3': 'FFF'
             }
         ]

Я хочу сравнить все элементы двух соответствующих словарей. Если какие-либо элементы не равны, я хочу напечатать неравные элементы.

Не могли бы вы помочь?

Ответы [ 6 ]

28 голосов
/ 23 марта 2012

Предполагая, что дикты выстраиваются, как в вашем примере ввода, вы можете использовать функцию zip(), чтобы получить список связанных пар диктов, затем вы можете использовать any(), чтобы проверить, есть ли разница:

>>> list_1 = [{'unique_id':'001', 'key1':'AAA', 'key2':'BBB', 'key3':'EEE'}, 
              {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
>>> list_2 = [{'unique_id':'001', 'key1':'AAA', 'key2':'DDD', 'key3':'EEE'},
              {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
>>> pairs = zip(list_1, list_2)
>>> any(x != y for x, y in pairs)
True

Или получить отличающиеся пары:

>>> [(x, y) for x, y in pairs if x != y]
[({'key3': 'EEE', 'key2': 'BBB', 'key1': 'AAA', 'unique_id': '001'}, {'key3': 'EEE', 'key2': 'DDD', 'key1': 'AAA', 'unique_id': '001'})]

Вы можете даже получить ключи, которые не совпадают для каждой пары:

>>> [[k for k in x if x[k] != y[k]] for x, y in pairs if x != y]
[['key2']]

Возможно вместе со связанными значениями:

>>> [[(k, x[k], y[k]) for k in x if x[k] != y[k]] for x, y in pairs if x != y]
[[('key2', 'BBB', 'DDD')]]

ПРИМЕЧАНИЕ: Если ваши входные списки еще не отсортированы, вы также можете сделать это легко:

>>> from operator import itemgetter
>>> list_1, list_2 = [sorted(l, key=itemgetter('unique_id')) 
                      for l in (list_1, list_2)]
5 голосов
/ 23 мая 2018

Самый быстрый и всеобъемлющий способ - использовать два sets из tuples:

set_list1 = set(tuple(sorted(d.items())) for d in list1)
set_list2 = set(tuple(sorted(d.items())) for d in list2)

Найти перекрывающихся используя intersection:

set_overlapping = set_list1.intersection(set_list2)

Найти разница с использованием symmetric_difference

set_difference = set_list1.symmetric_difference(set_list2)

Преобразование tuple обратно в dict

 for tuple_element in set_difference:
     list_dicts_difference.append(dict((x, y) for x, y in tuple_element))
2 голосов
/ 23 марта 2012

Ниже сравниваются словари и печатаются неравные позиции:

for d1, d2 in zip(list_1, list_2):
    for key, value in d1.items():
        if value != d2[key]:
            print key, value, d2[key]

Вывод: key2 BBB DDD.Используя zip, мы можем перебирать два словаря одновременно.Затем мы перебираем элементы первого словаря и сравниваем значение с соответствующим значением во втором словаре.Если они не равны, мы печатаем ключ и оба значения.

1 голос
/ 29 апреля 2015

У меня есть версия, которая на самом деле не зависит от конкретного ключа, поэтому элементы равны (нулю) или не равны (не нулю):

list_1 = [{'unique_id':'001', 'key1':'AAA', 'key2':'BBB', 'key3':'EEE'}, {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
list_2 = [{'unique_id':'001', 'key1':'AAA', 'key2':'DDD', 'key3':'EEE'}, {'unique_id':'002', 'key1':'AAA', 'key2':'CCC', 'key3':'FFF'}]
list_3 = [{'Name': 'Abid', 'Age': 27},{'Name': 'Mahnaz', 'Age': 27}]
list_4 = [{'Name': 'Abid', 'Age': 27},{'Name': 'Mahnaz', 'Age': 27}]

print cmp(list_1,list_1)
print cmp(list_1,list_3)
print cmp(list_1,list_2)
print cmp(list_2,list_1)
print cmp(list_3,list_4)

дает:

Return Value :  0
Return Value :  1
Return Value : -1
Return Value :  1
Return Value :  0
0 голосов
/ 06 января 2018
def new_change(old_list, new_list):
    change_list = []
    for x in new_list:
        for y in old_list:
            if x['unique_id'] != y['unique_id']:
                change_list.append(x)
    return change_list

передать старый и новый список в сторону этого метода

0 голосов
/ 25 апреля 2017
Let list1 = []
list2 = []

To fetch all the key values we can do like this:
key_values = list1[0]
key = key_values.keys() //key is a list and contains all key values

below is a piece of code which compares all the key pair values:

for val in list1:
    first_key = key[0]
    for val2 in list2:
        if val2[first_key] == val[first_key]:
            for val3 in key:
                if val2[val3] != val[val3]:
                    Unmatched.append(val)

print unmatched

Above contains matches dictionary and prints for which all key, pair values didn't match.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...