获取两者之间的异同 dicts/lists

Get differences and similarities between two dicts/lists

我有两个配置文件,基本上就是两个yamllists/dicts.

config_one: [{"ip": "0.0.0.0/24", "id": 1, "name": "First"},{"ip": "0.0.0.2/24", "id": 2, "name": "Second"},{"ip": "0.0.0.3/24", "id": 3, "name": "Third"}]
config_two: [{"ip": "0.0.0.3/24", "id": 30, "name": "Third"},{"ip": "0.0.0.0/24", "id": 1,"name": "First"}, {"ip": "0.0.0.2/24", "id": 2, "name": "Second"}]

我想将这两个配置文件相互比较,write/print 异同。 为了让它更有趣,假设“config_one”是“真相”,我希望如果有差异,也打印它应该是什么。

如果有匹配:

"First config - 0.0.0.0/24 - id: 1 can be found in config_two and is in line with expected "First config - 0.0.0.0/24 - id: 1" entry found in config_one"

如果“原样”config_two 和“应该”配置有差异:

"Third config - 0.0.0.3/24 - id: 30 can be found in config_two but is not in line with expected "Third config - 0.0.0.3/24 - id: 3" entry found in config one"

我尝试使用一些嵌套的 for 循环,但卡住了,并且永远无法真正找到在不陷入“无限循环”的情况下实际处理第二个列表中的键和值的方法。

   for i in config_one:
       for j in config_two:
         if i == j:
           print: i['name'] + i['ip'] + i['id'] + " matches " + j['name'] + j['ip'] + j['id']
         else:
           print i['name'] + i['ip'] + i['id'] + " does not match, it should be " + j['name'] + j['ip'] + j['id'] 
   

知道我该如何解决这个问题吗?

您可以尝试将列表转换为更容易比较的集合。 问题是集合只接受可散列的对象,所以你不能有一套字典。但是,使用简单的字典,您可以将它们转换为 可散列的等效数据结构,例如 (key, value) 元组列表。例如,第一个元素等同于集合 {('id', 2), ('ip', '0.0.0.2/24'), ('name', 'Second')}。这种情况下的另一个障碍是每个配置都需要一组集合,并且集合本身不可散列,因此您需要将内部集合变成 frozensets.

完成所有这些后,您可以尝试这样的操作:

>>> c1 = {frozenset(e.items()) for e in config_one}
>>> c2 = {frozenset(e.items()) for e in config_two}
>>> c1.symmetric_difference(c2)
{frozenset({('id', 3), ('ip', '0.0.0.3/24'), ('name', 'Third')}),
 frozenset({('id', 30), ('ip', '0.0.0.3/24'), ('name', 'Third')})}

如果配置可以放入内存,那么使用字典可以很容易地做到这一点。 (我假设我们需要根据键匹配各个配置 - 例如“ip”或“name”等)

config_one = [{"ip": "0.0.0.0/24", "id": 1, "name": "First"},{"ip": "0.0.0.2/24", "id": 2, "name": "Second"},{"ip": "0.0.0.3/24", "id": 3, "name": "Third"}]
config_two = [{"ip": "0.0.0.3/24", "id": 30, "name": "Third"},{"ip": "0.0.0.0/24", "id": 1,"name": "First"}, {"ip": "0.0.0.2/24", "id": 2, "name": "Second"}]

def compare_configs(config_one, config_two, key):
    matches = []
    differences = []
    missing = []
    lookup = {item[key]: item for item in config_two}

    for item in config_one:
        if item[key] in lookup:
            is_match = item == lookup[item[key]]
            if is_match:
                matches.append(item)
            else:
                differences.append((item, lookup[item[key]]))
        else:
            missing.append(item)

    return matches, differences, missing

matches, differences, missing = compare_configs(config_one, config_two, "ip")
print(matches)
print(differences)
print(missing)

这是结果:

[{'ip': '0.0.0.0/24', 'id': 1, 'name': 'First'}, {'ip': '0.0.0.2/24', 'id': 2, 'name': 'Second'}]
[({'ip': '0.0.0.3/24', 'id': 3, 'name': 'Third'}, {'ip': '0.0.0.3/24', 'id': 30, 'name': 'Third'})]
[]

这里我创建了三个列表,matchesdifferencesmissing

  • matches 包含每个列表中所有相同的配置
  • differences 包含与键匹配的配置,但其他一些值不同
  • missing 包含 config_one 中不在 config_two
  • 中的配置