Python:按列表元素首段ID分组统计对应元素个数
问题描述
给定如下列表:
['21,*,1', '21,stuff,1', '21,*,10', '21,stuff,4', '21,*,1', '21,*,114', '21,stuff,1', '28,*,37', '28,stuff,1', '28,*,4', '28,stuff,4', '28,*,4', '28,XXX,3', '28,stuff,1', '28,XXX,23', '28,XXX,87', '38,*,72', '38,stuff,9', '38,*,6', '38,stuff,32', '38,stuff,3', '38,stuff,3', '38,XXX,1', '38,*,23', '42,*,37', '42,XXX,1', '42,stuff,4']
需要按每个字符串逗号分割后的首段ID(ID始终升序排列)分组,统计每个ID对应的元素数量,示例输出为:
[['21', 7], ['28', 9], ['38', 8], ['42', 3]]
作为Python新手,寻求简洁优雅的实现方法。
实现方法
方法一:使用collections.defaultdict统计
这是最直观的计数方式,适合新手理解:
from collections import defaultdict data = ['21,*,1', '21,stuff,1', '21,*,10', '21,stuff,4', '21,*,1', '21,*,114', '21,stuff,1', '28,*,37', '28,stuff,1', '28,*,4', '28,stuff,4', '28,*,4', '28,XXX,3', '28,stuff,1', '28,XXX,23', '28,XXX,87', '38,*,72', '38,stuff,9', '38,*,6', '38,stuff,32', '38,stuff,3', '38,stuff,3', '38,XXX,1', '38,*,23', '42,*,37', '42,XXX,1', '42,stuff,4'] # 初始化默认值为0的字典,用于计数 count_dict = defaultdict(int) for s in data: # 拆分字符串,取首段作为ID id_ = s.split(',')[0] count_dict[id_] += 1 # 按ID升序排序,转成要求的二维列表格式 result = [[k, v] for k, v in sorted(count_dict.items())] print(result)
方法二:使用itertools.groupby(最简洁)
因为题目说明ID始终是升序排列的,groupby可以直接对连续相同ID的元素分组,代码更简洁:
from itertools import groupby data = ['21,*,1', '21,stuff,1', '21,*,10', '21,stuff,4', '21,*,1', '21,*,114', '21,stuff,1', '28,*,37', '28,stuff,1', '28,*,4', '28,stuff,4', '28,*,4', '28,XXX,3', '28,stuff,1', '28,XXX,23', '28,XXX,87', '38,*,72', '38,stuff,9', '38,*,6', '38,stuff,32', '38,stuff,3', '38,stuff,3', '38,XXX,1', '38,*,23', '42,*,37', '42,XXX,1', '42,stuff,4'] # 定义分组键:提取每个字符串的首段ID get_id = lambda x: x.split(',')[0] # 分组后统计每组长度,直接生成结果 result = [[key, len(list(group))] for key, group in groupby(data, get_id)] print(result)
方法三:使用collections.Counter
先提取所有ID,再用Counter统计次数,逻辑清晰:
from collections import Counter data = ['21,*,1', '21,stuff,1', '21,*,10', '21,stuff,4', '21,*,1', '21,*,114', '21,stuff,1', '28,*,37', '28,stuff,1', '28,*,4', '28,stuff,4', '28,*,4', '28,XXX,3', '28,stuff,1', '28,XXX,23', '28,XXX,87', '38,*,72', '38,stuff,9', '38,*,6', '38,stuff,32', '38,stuff,3', '38,stuff,3', '38,XXX,1', '38,*,23', '42,*,37', '42,XXX,1', '42,stuff,4'] # 提取所有ID组成列表 id_list = [s.split(',')[0] for s in data] # 统计每个ID的出现次数 counts = Counter(id_list) # 排序后转成目标格式 result = [[k, v] for k, v in sorted(counts.items())] print(result)
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

