获取两者之间的异同 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')}
。这种情况下的另一个障碍是每个配置都需要一组集合,并且集合本身不可散列,因此您需要将内部集合变成 frozenset
s.
完成所有这些后,您可以尝试这样的操作:
>>> 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'})]
[]
这里我创建了三个列表,matches
、differences
和missing
matches
包含每个列表中所有相同的配置
differences
包含与键匹配的配置,但其他一些值不同
missing
包含 config_one 中不在 config_two 中的配置
我有两个配置文件,基本上就是两个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')}
。这种情况下的另一个障碍是每个配置都需要一组集合,并且集合本身不可散列,因此您需要将内部集合变成 frozenset
s.
完成所有这些后,您可以尝试这样的操作:
>>> 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'})]
[]
这里我创建了三个列表,matches
、differences
和missing
matches
包含每个列表中所有相同的配置differences
包含与键匹配的配置,但其他一些值不同missing
包含 config_one 中不在 config_two 中的配置