Python - 以递归方式查找列表中的列表(n深)

时间:2016-10-15 12:55:30

标签: python networking recursion

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

我的BGP聚合地址为10.76.32.0/20

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

这种情况下的网络是:

10.76.32.0/24 10.76.33.0/24 10.76.34.0/24 10.76.35.0/24 10.76.36.0/24 10.76.37.0/24 10.76.38.0/24 10.76.39.0/24 10.76.40.0/24 10.76.41.0/24 10.76.42.0/24 10.76.43.0/24 10.76.44.0/25 10.76.44.128/25 10.76.45.0/24 10.76.46.0/24 10.76.47.240/30 10.96.208.219/32

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

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

我的问题是,如果有人知道如何在列表中找到任意深度的列表结构中的所有元素。

Hunor

编辑:感谢您的回答АндрейБеньковский。我没有时间检查它但是我确实找到了一种方法来实现它而不使用netaddr的.issubset方法的递归:

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'] < / p>

1 个答案:

答案 0 :(得分:0)

你没有指出你正在使用的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获得无效错误,但范围检查可以是添加了一些调整。

相关问题