Python - 将IP地址列表转换为地址范围列表

时间:2011-08-02 20:03:51

标签: python ip collapse

有多种方法可以将IP地址列表转换为CIDR列表(netaddr,ipaddr-py)。有没有办法将IP地址范围列表转换为合并的IP范围?

请注意,这是我previous question on glob formatting的一般性问题。

以下示例返回以下格式的元组列表:[(start, end)]

示例1:

>>> list_of_ips = ['192.168.0.1', '192.168.0.2', '192.168.0.3']
>>> print merge_ip_list(list_of_ips)
[('192.168.0.1','192.168.0.3')]

示例2:

>>> list_of_ips2 = ['10.0.0.0', '10.0.0.3', '10.0.0.4']
>>> print merge_ip_list(list_of_ips2)
[('10.0.0.0','10.0.0.0'), ('10.0.0.3','10.0.0.4')]

1 个答案:

答案 0 :(得分:3)

恕我直言,开始的一个好处是将转换器从虚线字符串转换为int和back。整数表示比较方便。

我想过使用reduce但对我来说似乎太难了。所以我刚刚使用传统循环实现它,没有递归。

def int2dot( intip ):
    return '.'.join([ str( (intip>>x*8) & 0xFF ) for x in [3,2,1,0]])
def dot2int( dotip ):
    return reduce( lambda r,x: int(x)+(r<<8), dotip.split('.'), 0 )

def merge_ip_list(ip_list):
    if not ip_list:
        return []
    orig = map(dot2int,ip_list)
    orig.sort()
    start = orig[0]
    prev = start-1
    res = []
    for x in orig:
        if x != prev+1:
            res.append((int2dot(start),int2dot(prev)))
            start = x
        prev = x
    res.append((int2dot(start),int2dot(prev)))
    return res

编辑:错误已修复。

我也做了另一种解决方案:

def merge_ip_list_alt(ip_list):
    if not ip_list:
        return []
    orig = sorted(map(dot2int,ip_list))
    end, start = zip(*[x for x in zip(orig,orig[1:]) if x[0]+1!=x[1]]) or ((),())
    start = [int2dot(orig[0])] + map(int2dot,start)
    end = map(int2dot,end) + [int2dot(orig[-1])]
    return zip( start, end )

让我给你一些未来的建议。不要让人们为你编写代码。我帮助你只是因为我有兴趣使代码尽可能小,并提高我自己的知识。但罗宾汉并不总是在这里。尝试自己开发一些东西,我们将帮助您找到算法和代码中的错误。