Pythonic way to find if an IP in a list belongs to a different subnet
Question: 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.


Answer: 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))
    

