сравнить два списка словарей для конкретных полей - PullRequest
0 голосов
/ 21 ноября 2018

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

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

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

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

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 ]

0 голосов
/ 21 ноября 2018

Вы можете использовать метод 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))
0 голосов
/ 21 ноября 2018

Кто-то уже создал модуль под названием 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 в вашем проекте!

0 голосов
/ 21 ноября 2018

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

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])
0 голосов
/ 21 ноября 2018

Если вы счастливы использовать стороннюю библиотеку, этот вид задачи может быть реализован более эффективно и более структурированно через 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 с каждого входа.

0 голосов
/ 21 ноября 2018

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

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
0 голосов
/ 21 ноября 2018

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

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!

0 голосов
/ 21 ноября 2018

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

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)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...