сравнить два списка словарей для определенных полей

У меня есть два списка, содержащие словари. Я хочу сравнить определенные поля в каждом из этих словарей.

current_list = [{"name": "Bill","address": "Home", "age": 23, "accesstime":11:14:01}, 
            {"name": "Fred","address": "Home", "age": 26, "accesstime":11:57:43},
            {"name": "Nora","address": "Home", "age": 33, "accesstime":11:24:14}]

backup_list = [{"name": "Bill","address": "Home", "age": 23, "accesstime":13:34:24}, 
           {"name": "Fred","address": "Home", "age": 26, "accesstime":13:34:26},
           {"name": "Nora","address": "Home", "age": 33, "accesstime":13:35:14}]

Список / словари должны быть одинаковыми по порядку, и я просто хочу сравнить определенные пары ключей и значений. Как имя, адрес, возраст и игнорировать время доступа, но то, что я до сих пор сравнивает каждый ключ / пару. Так что я просто хочу сравнить

current_list:dictionary[0][name] -> backup_list:dictionary[0][name] and then 
current_list:dictionary[0][address] -> backup_list:dictionary[0][address] 

и так далее.

for x in current_list:
    for y in backup_list:
        for k, v in x.items():
            for kk, vv in y.items():
                if k == kk:
                    print("Match: {0}".format(kk))
                    break
                elif k != kk:
                    print("No match: {0}".format(kk))

Токовый выход

Match name with name
No Match address with name
Match address with address
No Match age with name
No Match age with address
Match age with age
No Match dateRegistered with name
No Match dateRegistered with address
No Match dateRegistered with age
Match dateRegistered with dateRegistered

Предпочтительный выход

Match name with name
Match address with address
Match age with age

* Из-за изменения требований мой список стал списком элементов xml Elementtree *

Таким образом, вместо приведенного выше списка, он становится

backup_list =  ["<Element 'New' at 0x0000000002698C28>, <Element 'Update' at 0x0000000002698CC8>, <Element 'New' at 0x0000000002698CC8>"]

Где ElementTree - это элемент xml, содержащий:

{"name": "Nora", "address": "Home", "age": 33, "dateRegistered": 20140812}"

Таким образом, это, основываясь на приведенном ниже ответе, похоже, удовлетворяет моим требованиям:

value_to_compare = ["name", "address", "age"]
for i, elem in enumerate(current_list):
    backup_dict = backup_list[i]
    if elem.tag == "New":
        for key in value_to_compare:
            try:
                print("Match {0} {1} == {2}:".format(key, backup_dict.attrib[key], elem.attrib[key]))
            except KeyError:
                print("key {} not found".format(key))
            except:
                raise
    else:
        continue

Всего 7 ответов


Я не понимаю rationnal вашей структуры данных, но я думаю, что это сделает трюк:

value_to_compare = ["name", "address", "age"]

for i, elem in enumerate(current_list):
    backup_dict = backup_list[i]
    for key in value_to_compare:
        try:
            print("Match {}: {} with {}".format(key, elem[key], backup_dict[key]))
        except KeyError:
            print("key {} not found".format(key))
            # may be a raise here.
        except:
            raise

Я не знаю, полностью ли я понял ваш вопрос, но я думаю, что следующий код должен сделать трюк:

compare_arguments = ["name", "age", "address"]
for cl, bl in zip(current_list, backup_list):
    for ca in compare_arguments:
        if cl[ca] == bl[ca]:
            print("Match {0} with {0}".format(cl[ca]))
    print("-" * 10)

То, что сделано в приведенном выше коде, - это итерация zip по обоим спискам. В другом списке указаны поля, которые вы хотите сравнить. В основном цикле вы перебираете сравнимые поля и печатаете их соответствующим образом.


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

for dct1, dct2 in zip(current_list, backup_list):
    for k, v in dct1.items():
        if k == "accesstime":
            continue
        if v == dct2[k]:
            print("Match: {0} with {0}".format(k))
        else:
            print("No match: {0} with {0}".format(k))

Обратите внимание, что значения ваших ключей "accesstime" не являются допустимыми объектами Python!


Если вы счастливы использовать стороннюю библиотеку, такая задача может быть более эффективно реализована и более структурированно через Pandas:

import pandas as pd

res = pd.merge(pd.DataFrame(current_list),
               pd.DataFrame(backup_list),
               on=['name', 'address', 'age'],
               how='outer',
               indicator=True)

print(res)

  accesstime_x address  age  name accesstime_y _merge
0     11:14:01    Home   23  Bill     13:34:24   both
1     11:57:43    Home   26  Fred     13:34:26   both
2     11:24:14    Home   33  Nora     13:35:14   both

Результат _merge = 'both' для каждой строки указывает на комбинацию ['name', 'address', 'age'] в обоих списках, но, кроме того, вы можете видеть accesstime с каждого входа.


Вы можете использовать zip метод для перебора списков одновременно.

elements_to_compare = ["name", "age", "address"]
for dic1, dic2 in zip(current_list, backup_list):
    for element in elements_to_compare :
        if dic1[element] == dic2[element]:
            print("Match {0} with {0}".format(element))

Кто-то уже создал модуль под названием deepdiff, который делает это и оооооооооооооооооооооо !!! Обратитесь к этому ответу за подробное объяснение!

Сначала - установите его

pip install deepdiff

Затем - наслаждайтесь

#of course import it
from deepdiff import DeepDiff

current_list, backup_list = [...], [...] #values stated in question.

for c, b in zip(current_list, backup_list):
    dif = DeepDiff(c, b)
    for key in ["name", "age", "address"]:
        try:
            assert dif['values_changed'][f"root['{key}'"]
            #pass the below line to exclude any non-matching values like your desired output has
            print(f"No Match {key} with {key}")
        except KeyError:
            print(f"Match {key} with {key}")

Результаты: - как и ожидалось

Match name with name
Match address with address
Match age with age
Match name with name
Match address with address
Match age with age
Match name with name
Match address with address
Match age with age

Итоговая записка

Этот модуль имеет намного больше возможностей, которые вы можете использовать, например, изменения type изменения key / удаления / добавления, обширное сравнение text и поиск. Определенно хорошо стоит посмотреть.

~ GL на ваш проект!


Просто сравните с этим -

for current in current_list:
    for backup in backup_list:
        for a in backup:
            for b in current:
                if a == b:
                    if a == "name" or a== "age" or a== "address" :
                        if backup[a] == current[b]:
                            print (backup[a])
                            print (current[b])