groupby模块

groupby()把迭代器中相邻的重复元素挑出来放在一起:

import itertools
for key, group in itertools.groupby('AAABBBCCAAA'):
print key, list(group) #因为group是一个迭代器,所以这里要用这里要用list()函数

A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
A ['A', 'A', 'A']

挑选规则是通过函数完成的,只要作用于函数的两个元素返回的值相等,这两个元素就被认为是同一组的,而函数返回值作为组的key

 

例子1:将相同国家的人员信息进行归纳

d1={'name':'Lilei','age':15,'country':'China'}
d2={'name':'jack','age':19,'country':'USA'}
d3={'name':'苍老师','age':22,'country':'JP'}
d4={'name':'tom','age':22,'country':'USA'}
d5={'name':'lucy','age':22,'country':'USA'}
d6={'name':'Hanmeimei','age':15,'country':'China'}
lst=[d1,d2,d3,d4,d5,d6]

from itertools import groupby

#必须先排序,才可以分组
lst.sort(key=lambda x:x['country'])
print(lst)
# [{'name': 'Lilei', 'age': 15, 'country': 'China'}, {'name': 'Hanmeimei', 'age': 15, 'country': 'China'}, {'name': '苍老师', 'age': 22, 'country': 'JP'}, {'name': 'jack', 'age': 19, 'country': 'USA'}, {'name': 'tom', 'age': 22, 'country': 'USA'}, {'name': 'lucy', 'age': 22, 'country': 'USA'}]


lst_g = groupby(lst,key=lambda x:x['country'])
print(list(lst_g))
# [('China', <itertools._grouper object at 0x000002ACC7105A90>), ('JP', <itertools._grouper object at 0x000002ACC7105B00>), ('USA', <itertools._grouper object at 0x000002ACC7105EB8>)]


for c, g in lst_g:
    print({c:[v for v in g]})

# {'China': [{'name': 'Lilei', 'age': 15, 'country': 'China'}, {'name': 'Hanmeimei', 'age': 15, 'country': 'China'}]}
# {'JP': [{'name': '苍老师', 'age': 22, 'country': 'JP'}]}
# {'USA': [{'name': 'jack', 'age': 19, 'country': 'USA'}, {'name': 'tom', 'age': 22, 'country': 'USA'}, {'name': 'lucy', 'age': 22, 'country': 'USA'}]}

例子2:归纳列表中连续的数字

from itertools import groupby

lst = [2, 3, 5, 6, 7, 8,1, 11, 12, 13,15,27,28,29]

lst.sort()
print(lst)
# [1, 2, 3, 5, 6, 7, 8, 11, 12, 13, 15, 27, 28, 29]

print(list(enumerate(lst)))
# [(0, 1), (1, 2), (2, 3), (3, 5), (4, 6), (5, 7), (6, 8), (7, 11), (8, 12), (9, 13), (10, 15), (11, 27), (12, 28), (13, 29)]
#  相连的整数与序号的差值是相等的,所以可以归纳为一组

# for k, g in groupby(enumerate(lst), key=lambda x:x[1]-x[0]):
#     print(list(g))
# [(0, 1), (1, 2), (2, 3)]
# [(3, 5), (4, 6), (5, 7), (6, 8)]
# [(7, 11), (8, 12), (9, 13)]
# [(10, 15)]
# [(11, 27), (12, 28), (13, 29)]

for k, g in groupby(enumerate(lst), key=lambda x:x[1]-x[0]):
    print([v for i,v in g])
    # [1, 2, 3]
    # [5, 6, 7, 8]
    # [11, 12, 13]
    # [15]
    # [27, 28, 29]

例子3:归纳列表中连续的ip

import ipaddress

ip_list = [
'10.16.49.113',
'10.202.255.127',
'10.202.255.125',
'10.202.255.126',
'10.202.255.145',
'10.202.255.175',
'10.202.255.174',
'10.202.255.144',
'10.202.255.173'
]

ip_list_int = [ipaddress.ip_address(ip) for ip in ip_list]
ip_list_int.sort()
# print(ip_list_int)


ip_list_int = [int(ipaddress.ip_address(ip)) for ip in ip_list]
ip_list_int.sort()
# print(ip_list_int)
# [168833393, 181075837, 181075838, 181075839, 181075856, 181075857, 181075885, 181075886, 181075887]

rst = []

for i,j in groupby(enumerate(ip_list_int), key=lambda x:x[1]-x[0]):
    # print(list(j))
    # [(0, 168833393)]
    # [(1, 181075837), (2, 181075838), (3, 181075839)]
    # [(4, 181075856), (5, 181075857)]
    # [(6, 181075885), (7, 181075886), (8, 181075887)]

    # print([v for k,v in j])
    # [168833393, 181075837, 181075838, 181075839, 181075856, 181075857, 181075885, 181075886, 181075887]
    # [168833393]
    # [181075837, 181075838, 181075839]
    # [181075856, 181075857]
    # [181075885, 181075886, 181075887]

    ip_range_list = [v for k,v in j]
    if len(ip_range_list)>1:
        ip_range = ipaddress.summarize_address_range(ipaddress.ip_address(ip_range_list[0]),ipaddress.ip_address(ip_range_list[-1]))
        for ip_summ in ip_range:
            rst.append(str(ip_summ))
    else:
      rst.append(str(ipaddress.ip_address(ip_range_list[0])))

print(rst)
# ['10.16.49.113', '10.202.255.125/32', '10.202.255.126/31', '10.202.255.144/31', '10.202.255.173/32', '10.202.255.174/31']

 

 

上一篇: 案例研究 - 应用程序模型


下一篇:Python 简明教程 --- 20,Python 类中的属性与方法