如何用Python分割不连续的有序列表


=Start=

缘由:

同事需要实现一个功能:从指定IP段中排除某些IP或IP段,最后得到一个类似于IP区间的结果格式。比如:

$ python py_exclude_ip_cidr.py 10.32.0.0/16 10.32.0.0/24 10.32.26.254 10.32.104.199
10.32.1.0-10.32.26.253
10.32.26.255-10.32.104.198
10.32.104.200-10.32.255.255
正文:
理清思路:

将CIDR格式的IP段转换成大整数区间的格式,然后再从这个大区间中剔除「要排除的小区间」,然后将区间的首尾整数转换成IP地址的格式。

提取出的问题:

其中碰到的一个问题就是,将一个「不一定连续」的有序列表转换成「一个或多个」连续有序列表。

参考解答:

实现一个函数myfunc,传入不一定连续的列表,返回一个包含多个区间的列表,比如:

myfunc([2, 3, 4, 5, 12, 13, 14, 15, 16, 17, 20])

返回:

[(2,5), (12,17), 20]

==

from operator import itemgetter
from itertools import groupby

ranges = []
data = [2, 3, 4, 5, 12, 13, 14, 15, 16, 17]
for k, g in groupby(enumerate(data), lambda (i,x):i-x):
    group = map(itemgetter(1), g)
    ranges.append((group[0], group[-1]))
    print group
print ranges
>>> # Show a dictionary sorted and grouped by value(Python中根据dict中元素出现的次数进行分组)
>>> from operator import itemgetter
>>> d = dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3)
>>> di = sorted(d.iteritems(), key=itemgetter(1))
>>> for k, g in groupby(di, key=itemgetter(1)):
...     print k, map(itemgetter(0), g)
...
1 ['a', 'c', 'e']
2 ['b', 'd', 'f']
3 ['g']

>>> # Find runs of consecutive numbers using groupby.  The key to the solution
>>> # is differencing with a range so that consecutive numbers all appear in
>>> # same group.(将list中连续的串进行分组)
>>> data = [ 1,  4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
>>> for k, g in groupby(enumerate(data), lambda (i,x):i-x):
...     print map(itemgetter(1), g)
...
[1]
[4, 5, 6]
[10]
[15, 16, 17, 18]
[22]
[25, 26, 27, 28]
参考链接:

=END=


《“如何用Python分割不连续的有序列表”》 有 1 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注