Reputation: 73
I have a script that generates the configuration for some campus wireless mobility switches. The user needs to supply a set of IP addresses for the configuration.
Among other constraints, these IP's must all be in the same /24 subnet (always /24). To avoid typos where an IP is in a different subnet (which messes up the configuration and it happened already), I would like to tell the user which IP is at fault. I wrote the following, but I feel there could be a better way to do it.
Suppose the list is this, where the 3rd IP is wrong:
ips = ['10.0.0.1', '10.0.0.2', '10.0.10.3', '10.0.0.4', '10.0.0.5']
The following gets the job done:
subnets = set()
for ip in ips:
subnets.add('.'.join(ip.split('.')[0:3]))
# This would result in subnet being set(['10.0.10', '10.0.0'])
if len(subnets) > 1:
seen_subnets = defaultdict(list)
for sn in subnets:
for ip in ips:
if sn in ip:
seen_subnets[sn].append(ip)
suspect = ''
for sn in seen_subnets.keys():
if len(seen_subnets[sn]) == 1:
suspect = seen_subnets[sn][0]
if not suspect:
# Do something to tell the user one or more IP's are incorrect
# but I couldn't tell which ones
NOTE: The smallest list that I could have has 3 items, and I'm basing this on the assumption that probably most if not all mistakes will be just 1 IP.
Is there perhaps a more straightforward way to do this? I feel the solution has to be based on using a set
either way but it didn't seem to me any of its methods would be more helpful than this.
Upvotes: 0
Views: 51
Reputation: 29690
Something like this would work:
from itertools import groupby
ips = ['10.0.0.1', '10.0.0.2', '10.0.10.3', '10.0.0.4', '10.0.0.5']
def get_subnet(ip):
return '.'.join(ip.split('.')[:3])
groups = {} # group ips by subnet
for k, g in groupby(sorted(ips), key=get_subnet):
groups[k] = list(g)
# Sort the groups by most common first
for row, (subnet, ips) in enumerate(
sorted(groups.iteritems(), key=lambda (k, v): len(v), reverse=True)
):
if row > 0: # not the most common subnet
print('You probably entered these incorrectly: {}'.format(ips))
Upvotes: 1