Python -递归地在列表(n深度)中查找列表



我试图使用ipaddress (https://docs.python.org/3/library/ipaddress.html)来解决以下问题:

我有一个BGP聚合地址10.76.32.0/20

我想从中减去同一路由器上的所有网络命令,以确定聚合地址是否大于定义的网络,是否有剩余的空闲网络空间。

本例中的网络为:

10.76.32.0/2410.76.33.0/2410.76.34.0/2410.76.35.0/2410.76.36.0/2410.76.37.0/2410.76.38.0/2410.76.39.0/2410.76.40.0/2410.76.41.0/2410.76.42.0/2410.76.43.0/2410.76.44.0/2510.76.44.128/2510.76.45.0/2410.76.46.0/2410.76.47.240/3010.96.208.219/32

使用ipaddress.address_exclude(network)可以从聚合地址中减去一个网络,该操作返回一个可迭代对象。

然后我可以在这个可迭代对象上创建一个for循环,看看它是否包含任何其他网络,但如果它包含,我将得到另一个可迭代对象作为结果。这个过程可以假设返回列表中的列表到一个未指定的深度。

我的问题是,是否有人知道一种方法可以在任意深度的列表中找到这种列表结构中的所有元素。

Hunor

编辑:谢谢你的回答АндрейБеньковский。我还没有时间去检查它,但我确实找到了一种方法来做到这一点,而不使用递归与。is子集方法从netaddr:

def undeclared_in_aggregate(aggregate, network):
    remaining = []
    composite = []
    for a_cidr in aggregate:
        a_cidr = IPSet([a_cidr])
        for n_cidr in network:
            n_cidr = IPSet([n_cidr])
            if n_cidr.issubset(a_cidr):
                a_cidr.remove(n_cidr.iprange())
                remaining = re.sub(r'IPSet([|])|'', '', str(a_cidr))
                remaining = remaining.split(',')
                if remaining == ['']:
                    remaining = []
        composite += remaining
    return composite

这将以列表格式获取聚合地址和网络,并以新列表的形式返回差值(每个聚合地址)。

为上面的例子:(‘10.76.47.0/25’,‘10.76.47.128/26’,‘10.76.47.192/27’,‘10.76.47.224/28’,‘10.76.47.244/30’,‘10.76.47.248/29]

您没有指出您正在使用的python(2或3)版本,因此我假设它是python3基于您发布的链接是python3文档的事实。您没有发布任何代码,但根据您对问题的描述,我认为您需要这样的东西:

from ipaddress import ip_network, summarize_address_range
from itertools import chain
def exclude_multiple(super_network, networks):
    networks = sorted(networks, key=lambda n:n.network_address)
    starts = (n.broadcast_address + 1 for n in networks)
    starts = chain([super_network.network_address], starts)
    ends = (n.network_address - 1 for n in networks)
    ends = chain(ends, [super_network.broadcast_address])
    return ((s, e) for s, e in zip(starts, ends) if s != e + 1)  # s-1 != (e+1) - 1
networks = [
 '10.76.32.0/24',
 '10.76.33.0/24',
 # more here
]
networks = map(ip_network, networks)
super_network = ip_network('10.76.32.0/20')
free_ranges = exclude_multiple(super_network, networks)
free_networks = (summarize_address_range(f, l) for f, l in free_ranges)
free_networks = list(chain.from_iterable(free_networks))

这个代码不包括范围检查,所以如果networks重叠或走到super_network之外,你会从summarize_address_range得到一个没有非常有用的错误,但是范围检查可以添加一些调整。

最新更新