pythonip-address

Sorting a list of IP addresses into unique network address with the ranges of host addresses


I have a list of IP addresses from an API call:

ips = ["10.135.0.80","10.135.0.81","10.135.0.83","10.135.1.200","10.135.1.220","10.160.150.2","10.160.150.7","10.255.255.2"]

I want to have a list of IP addresses that looks like:

ips = ["10.135.0.80-10.135.0.83","10.135.1.200-10.135.1.220","10.160.150.2-10.160.150.7","10.255.255.2-10.255.255.2"]

Or a result based on the suggested answer:

ips = [("10.135.0.80", "10.135.0.83"),("10.135.1.200", "10.135.1.220"),("10.160.150.2", "10.160.150.7"),("10.255.255.2","10.255.255.2")]

If the network address is equal join the smallest to largest host address. If there is one host address per network address create a range out of said host address. If the network address is different start a new element and repeat.

I've read a number of other posts where they say to use socket module and bitwise operators to sort through IP addresses which is how the original IP list gets sorted:

sortedAddresses = sorted(
    ips, key=lambda ip: struct.unpack("!L", inet_aton(ip))[0]
)

The networks I can smash together really easy with some regex and make them all unique:

net = []
host = []
for ip in sortedAddresses:
    l = re.split("(.*)\\.(.*)\\.(.*)\\.(.*)", ip)
    net.append(l[1:-2])
    host.append(l[4:-1])
networks = []
for l in net:
    if l not in networks:
        networks.append(l)
hosts = []
for l in host:
    for e in l:
        hosts.append(e)
print(networks)
print(hosts)

Print Networks: [['10', '135', '0'], ['10', '135', '1'], ['10', '160', '150'], ['10', '255', '255']]

Print Hosts:['80', '81', '83', '200', '220', '2', '7', '2']

I think Joran's answer here with the socket module is the closest thing I've found to being my solution. I just can't figure out how I would sort through the list of hosts to determine the start and end in my original list or hosts list.

The suggested answer I received before posting is close as well except it would create to many ranges. I want the network addresses to be unique per range.


Solution

  • The folowing code:

    import itertools
    
    ips = [
        "10.135.0.80",
        "10.135.0.81",
        "10.135.0.83",
        "10.135.1.200",
        "10.135.1.220",
        "10.160.150.2",
        "10.160.150.7",
        "10.255.255.2",
    ]
    for _, v in itertools.groupby(ips, lambda v: v.split(".")[:3]):
        v = sorted(list(v), key=lambda x: int(x.split(".")[3]))
        low = v[0]
        high = v[-1]
        print(f"{low}-{high}")
    

    outputs:

    10.135.0.80-10.135.0.83
    10.135.1.200-10.135.1.220
    10.160.150.2-10.160.150.7
    10.255.255.2-10.255.255.2