Matching values in two lists of dictionaries

1.2k views Asked by At

Crew,

I've distilled the following two list of dictionaries from two of my switches. The first one from our core switch, the second one from access 'switch1'. In order to get more insight in to this network I want to cross reference these two lists of dictionaries.

core_table = [
{'ip': '172.17.2.1', 'mac': 'b8:27:eb:a3:24:a0', 'host': 'laptop', 'if': 'switch1'}, 
{'ip': '172.17.6.3', 'mac': '0c:89:10:88:20:3f', 'host': 'desktop', 'if': 'switch3'},
{'ip': '172.17.7.2', 'mac': 'b8:27:eb:a3:24:a3', 'host': 'server', 'if': 'switch1'}, 
{'ip': '172.17.6.2', 'mac': '0c:89:10:88:20:3f', 'host': 'storage', 'if': 'switch2'}
]

switch1_table = [
{'mac': '00:01:02:71:44:59', 'if': 'ge-1/0/6.0'},
{'mac': '00:06:73:00:c9:7a', 'if': 'ge-3/0/2.0'},
{'mac': 'b8:27:eb:a3:24:a0', 'if': 'ge-5/0/27.0'}, 
{'mac': '00:09:0f:09:1d:06', 'if': 'ae0.0'},
{'mac': '00:0a:07:05:1f:a4', 'if': 'ge-2/0/15.0'}, 
{'mac': '00:0b:4f:5d:09:ae', 'if': 'ge-2/0/19.0'},
{'mac': '00:0b:4f:d3:7b:3f', 'if': 'ge-1/0/18.0'}, 
{'mac': '00:0c:29:49:64:12', 'if': 'ae0.0'},
{'mac': '00:0e:ec:e8:18:50', 'if': 'ae0.0'}, 
{'mac': 'b8:27:eb:a3:24:a3', 'if': 'ge-0/0/44.0'}, 
{'mac': '00:15:17:93:aa:01', 'if': 'ae0.0'}
]

I can sum up all the mac addresses in the core_table:

for x in [m['mac'] for m in core_table]:
     print x
     print m

If I print m I see only the last dictionary in the list.

And likewise all the interfaces in access_table:

for y in [n['if'] for n in ex_table]:
      print y
      print n

It seems that this article: Python - accessing values nested within dictionaries is close to what I need but this relies on a relation between the entries within one list of dictionaries. This is not the case.

I can't find a way to iterate over core_table while matching mac adresses with the switch1_table. If a mac address in core_table matches a mac address in swicth1_table I'd like to print the corresponding line of the core_table AND the 'if' value of the access_table. What I'd like to achieve:

{'ip': '172.17.2.1', 'mac': 'b8:27:eb:a3:24:a0', 'host': 'laptop', 'if': 'switch1' 'port': 'ge-5/0/27.0'},
{'ip': '172.17.7.2', 'mac': 'b8:27:eb:a3:24:a3', 'host': 'server', 'if': 'switch1' 'port': 'ge-0/0/44.0'}

I've come up with: (Thank you: Pythonic Way to Compare Values in Two Lists of Dictionaries)

match = [x['mac'] for x in core_table if 'switch1' in x['if']]
print [x for x in switch1_table if x['mac'] in match]

This is getting me close but now I can't find a way to add the host and ip data.

Any suggestions are welcome.

2

There are 2 answers

2
GustavoIP On BEST ANSWER
for x in [m['mac'] for m in core_table]:
     print x
     print m

You should not try to access m externally. See this.

List Comprehensions were created to simplify things and turn the code cleaner. If you use them in many nested levels you are perverting their purpose. For Python 2.7.x

from copy import copy

result = []
for item in core_table:
    for item2 in swicth1_table:
        if item['mac'] == item2['mac']:
            new_item = copy(item)
            new_item['port'] = item2['if']
            result.append(new_item)

Output

{'port': 'ge-5/0/27.0', 'ip': '172.17.2.1', 'mac': 'b8:27:eb:a3:24:a0', 'host': 'laptop', 'if': 'switch1'}
{'port': 'ge-0/0/44.0', 'ip': '172.17.7.2', 'mac': 'b8:27:eb:a3:24:a3', 'host': 'server', 'if': 'switch1'}
2
Patrick Haugh On

I'd make a copy of switch1_table as a dictionary mapping mac addresses to dictionaries, then use that table to pull the relevant rows of core_table.

switch_dict = {v['mac']:v for v in switch1_table}
for c in core_table:
    if c['mac'] in switch_dict:
        print(dict(port=switch_dict[c['mac']]['if'], **c))

prints

{'ip': '172.17.2.1', 'host': 'laptop', 'if': 'switch1', 'mac': 'b8:27:eb:a3:24:a0', 'port': 'ge-5/0/27.0'}
{'ip': '172.17.7.2', 'host': 'server', 'if': 'switch1', 'mac': 'b8:27:eb:a3:24:a3', 'port': 'ge-0/0/44.0'}