计数相信大家都不陌生,简单来讲,就是统计数据结构中某一元素出现的次数。实际应用中很多这种需求,如检测一个样本中某一元素出现的次数、日志分析中某一条日志出现的次数、文件中某一个字符或者字符串出现的频率、词云生成中某一个词语出现的概率等等。这种需求有很多中实现方法。
今天,我们对Python计数实现方法进行梳理。
Python计数统计方式梳理 通用方法(一般思路)
使用字典解决(dict)字典计数是最常用的计数方法,逐个遍历数据结构中元素,将元素作为键,元素个数作为值进行统计,依次加入字典中。
实例演示
test_lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'f', 's', 'b', 'h', 'k', 'i', 'j', 'c', 'd', 'f']
counter_dict = {}
for item in test_lst:if item in counter_dict: counter_dict[item] += 1 else: counter_dict[item] = 1print(counter_dict)
程序运行结果>>>{'i': 1, 'a': 2, 's': 1, 'g': 1, 'b': 2, 'k': 1, 'h': 1, 'j': 1, 'c': 2, 'e': 1, 'd': 2, 'f': 3}
使用dict.setdefault(key, dvalue)方法解决可以使用dict.setdefault()方式进行统计,比起直接使用dict,该方法不用使用if-else语句进行判断,且避免了KeyError异常。
实例演示
test_lst = ['a', 'b', 'c', 'd', 'eshi', 'f', 'g', 'a', 'f', 's', 'b', 'h', 'k', 'i', 'j', 'c', 'd', 'f']
counter_sdict = {}for item in test_lst:counter_sdict[item] = counter_sdict.setdefault(item, 0) + 1print(counter_sdict)
程序运行结果>>>{'k': 1, 'e': 1, 'c': 2, 'a': 2, 'b': 2, 'd': 2, 'f': 3, 'g': 1, 's': 1, 'j': 1, 'i': 1, 'h': 1}
同dict方法,但程序的容错性比上面的方法要好,且数据量大时,该程序比使用dict的传统方法要节省时间。
使用defaultdict类解决defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,它自动实例化一个值作为默认值。使用defaultdict与使用dict的区别在于,defaultdict能够自动对获取结果进行排序,这就解决了我们后续排序的麻烦,并且defaushltdict是自带“轮子”,就不用重新创造了,节省开发时间哦。
实例演示
from collections import defaultdict
test_lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'f', 's', 'b', 'h', 'k', 'i', 'j', 'c', 'd', 'f']
counter_ddict = defaultdict(int)for item in test_lst:counter_ddict[item] += 1print(counter_ddict)
程序运行结果>>>defaultdict(<class 'int'>, {'k': 1, 'e': 1, 'c': 2, 'a': 2, 'b': 2, 'd': 2, 'f': 3, 'g': 1, 's': 1, 'j': 1, 'i': 1, 'h': 1})
结合使用set和list两种数据结构来解决思路如下:首先,初始化一个set和一个列表list,获取序列中需要统计的元素;然后,依次遍历set中的内容,使用需要统计序列的cosut()方法,分别统计set中的内容并计入新列表中。
实例演示
test_lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'f', 's', 'b', 'h', 'k', 'i', 'j', 'c', 'd', 'f']
r_lst = []temp = set(test_lst)for item in temp:r_lst.append((item, test_lst.count(item)))print(r_lst)
程序运行结果>>>[('j', 1), ('k', 1), ('a', 2), ('s', 1), ('d', 2), ('h', 1), ('f', 3), ('c', 2), ('e', 1), ('b', 2), ('i', 1), ('g', 1)]
更加pythonic的解决方案
上面的方法都显式的使用了for循环遍历,Python中有没有一种数据结构,直接对序列中元素逐个统计的呢?看下面的例子
实例演示
from collections import Counter
test_lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'f', 's', 'b', 'h', 'k', 'i', 'j', 'c', 'd', 'f']
print(Counter(test_lst))
程序运行结果>>>Counter({'f': 3, 'b': 2, 'd': 2, 'a': 2, 'c': 2, 'h': 1, 'e': 1, 'k': 1, 'j': 1, 's': 1, 'g': 1, 'i': 1})
使用Counter类只需要三行代码就可以解决哦,怎么样?是不是很方便?下面,我们对Counter的使用方法进行一个梳理。
Counter类的使用
Counter是字典类的子类,继承字典的方法,是一个容器对象,主要用于统计散列对象,并且它支持集合操作+、-、&、|,其中‘&’、‘|’分别返回两个Counter对象各个元素的最大值和最小值。
Counter类的实例初始化
Counter('Hello World')Counter(a=1, b=2, c=3)Counter({'a':1,'b':2,'c',3})获取Counter类的实例的key值
Counter(somedata).elements():它返回一个可迭代对象,使用list(Counter(somedata).elements())、tuple(Counter(somedata).elements())等结构可以将这个对象转化为我们常用的数据结构。
找到Counter类的实例中前N个出现频率最高的元素及响应的出现次数
Counter(somedata).most_common(N)
优点:当访问不存在的元素时,默认返回0,不会抛出异常。
其它常用方法
Counter(s).update(d):被统计元素的更新,传入一个序列d,将原有s中的统计数据与d中的统计数据相加,不会覆盖s中存在的内容。Counter(s).substract(d):实现计数器对象中元素统计值相减的功能,且强大之处在于其输入和输出的统计值可以为0或者负数。原创作品不易,转载请注明出处(百家号:Python高手养成)