当前位置: 首页 > news >正文

python Counter

# Python Counter:一个被低估的数据结构

提到Python的collections模块,很多人第一反应是defaultdict或者namedtuple,Counter常常被当作“统计列表元素出现次数”的小工具。但深入了解后就会发现,它远不止这么简单。

它到底是什么

Counter本质上是dict的子类,专门设计用来计数的字典。它继承了dict的所有特性——哈希查找、可变、可迭代——同时添加了计数场景下的便捷方法。它的键是你要统计的元素,值是该元素出现的次数。

举个例子,你有一篮子水果,用Counter统计后得到的是“苹果:3个,香蕉:2个,橙子:1个”这样的结构。它就像一个自动计数的记账本,不需要手动维护数字的变化。

有意思的是,Counter对缺失键的处理很优雅:如果你问“葡萄有多少个?”,它不会报错,而是返回0。这一点让我觉得比普通dict更符合直觉——当你需要知道不存在的东西有多少时,答案当然是零。

它能做什么

除了基础计数,Counter的能力圈其实更大。它实现了集合运算,可以用来做交集、并集、差集,但不是对元素本身操作,而是对计数进行操作。

想象你在管理两个仓库的库存——第一个仓库有5支笔、3本书,第二个仓库有2支笔、4本书。用Counter的交集运算可以得到“两个仓库都有的物品,取较少数量”的结果:就是2支笔。这听起来像什么?对,像是数据库里的join操作,但用一行代码就能完成。

它还能找出出现次数最多的元素。这个功能在文本分析中特别有用——统计文章中最常见的词、日志文件中出现频率最高的错误代码、电商订单中最火的商品。most_common方法带有内置排序,时间复杂度是O(n log k),其中k是你想取的前几位数。如果只取一位,效率会比全排序高不少。

怎么使用

创建

fromcollectionsimportCounter# 从可迭代对象创建c1=Counter(['苹果','香蕉','苹果','橙子','香蕉','苹果'])# 从字典创建c2=Counter({'苹果':3,'香蕉':2,'橙子':1})# 使用关键字参数c3=Counter(苹果=3,香蕉=2)# 最常见的方式:从字符串统计字符c4=Counter('hello world')

日常操作

遍历一个Counter时,默认遍历的是键而不是键值对,这一点和普通dict不同:

c=Counter(a=3,b=2,c=1)foriteminc:print(item)# 只打印键

如果同时需要键和值,需要用items()方法,这和普通dict一样。

增删改

给Counter增加计数很简单,直接添加元素即可:

c=Counter()c.update(['a','b','a','c'])# 现在c = Counter({'a': 2, 'b': 1, 'c': 1})

删除元素可以用del,也可以用subtract方法。但要注意subtract允许负值存在,这有时会造成一些小陷阱——某个元素计数变成负值后,你要么手动清理,要么在获取时用+操作符过滤掉负数。

找前几位

c=Counter('abracadabra')print(c.most_common(3))# 输出 [('a', 5), ('b', 2), ('c', 2)]

most_common不传参数时返回所有元素按次数降序排列。但如果Counter有大量不同元素,这种全量排序可能会有点慢。

最佳实践

不要用Counter做高频计数。如果你需要在每秒百万次的循环中累加计数,Counter的字典查找开销可能成为瓶颈。这时候用numpy数组或者简单的list索引会更高效。我曾经在一个实时日志处理场景中犯过这个错——Counter写起来漂亮,但压测时发现CPU都在哈希表的扩容上。

利用+和-操作符合并计数器时注意边界。Counter的加法是把对应计数相加,减法则会把结果截断到0以下——这和集合差集操作的行为一致,但有时会误导新手。如果你需要计数不能为负,可以这样做:

c1=Counter(a=1,b=3)c2=Counter(a=2,b=1)result=c1-c2# 结果是Counter({'b': 2}),a被去掉了因为1-2<0

如果想让a的结果是0而不是被删除,可以用字典推导式来转换。

用Counter当作多集合。有些场景下,Counter比set更好用。比如你需要检查两个列表是否有重叠元素,不仅要知道是否重叠,还要知道重叠了多少次。set只能给出布尔结果,而Counter的&操作能给出精确的交集计数。

慎用Counter作为value的容器。有些人喜欢把Counter嵌套在字典里当统计工具用,但这容易导致内存膨胀——每个嵌套的Counter都是一个独立对象。如果统计维度很多,可以考虑用pandas的groupby或者SQL的聚合函数。

和同类技术对比

对比普通dict

使用普通dict计数需要手动处理KeyError:

d={}foriteminitems:ifitemind:d[item]+=1else:d[item]=1

Counter把这段样板代码压缩成一行:Counter(items)。但这不只是语法糖,Counter还额外提供了most_common、elements、subtract等实用方法,以及集合操作。

不足之处在于,Counter引入了浮动开销。如果你的代码对内存敏感,或者只需要最简单的计数(比如只取最后统计结果),普通dict配合defaultdict可能更快。

对比defaultdict

defaultdict(int)也能做自动计数,写起来类似:

fromcollectionsimportdefaultdict d=defaultdict(int)foriteminitems:d[item]+=1

这个方法比Counter快,因为defaultdict直接继承自dict,没有Counter的额外方法。如果只需要计数功能,defaultdict是更好的选择。但如果你需要most_common或集合运算,就得自己实现了。

对比numpy/pandas

在数据量非常大时(百万级以上),Python原生的Counter和dict都会遇到性能瓶颈。numpy的bincount或者pandas的value_counts在大规模数值型数据上表现更好。pandas的value_counts甚至支持更复杂的操作,比如按比例显示、排序方式、缺失值处理等。

不过这些工具也有门槛——numpy只能处理整数类型,pandas需要事先把数据加载到DataFrame中。如果是零散的小数据,Counter的便携性完胜。

简单总结一下:Counter最擅长的是中小规模数据的快速统计,需要同时兼顾计数和查询的场景,以及需要集合运算的场合。性能敏感的地方用defaultdict,规模大的地方用pandas,高频操作还是用裸循环+索引更稳。

http://www.jsqmd.com/news/689219/

相关文章:

  • IEC61850 ICD文件扩展实战:为智能设备新增DO节点的完整指南
  • 用Python视角拆解Google AMIE首次真实世界临床验证(下)
  • 深入TI毫米波雷达芯片:从射频前端到ARM/DSP双核,如何分配算法任务?
  • 超越COCO的21K类别检测:用C#和Detic模型打造你的“万物识别”小工具
  • Qwen2.5-VL-7B-Instruct效果展示:多图时序理解(如实验过程连贯分析)
  • 低年级娃学习兴趣难培养?这5款适龄APP,无痛启蒙不费妈 - 品牌测评鉴赏家
  • HoloEverywhere:终极Android主题兼容解决方案 - 让旧设备享受现代UI体验
  • 用LLaMA-Factory快速微调第一个开源大模型(新手指南)-实战落地指南
  • 终极指南:5步掌握Cursor Pro破解工具,实现无限AI编程自由
  • 从集合操作到代码实现:一文搞懂杰卡德相似系数在Python中的三种高效写法(附性能对比)
  • 手把手带你用Wireshark抓包分析UFS协议:实战解读UPIU数据单元与链路训练过程
  • YouTube Plus网络设置:Wi-Fi和移动数据下载控制的终极指南
  • STM32F407双ADC同步规则转换+双ADC交替采样+DMA搬运+DAC输出ADC采样+定时器触发+HAL库+cubemx配置详解
  • 从像素到画布:手把手教你用JavaScript玩转ImageData,实现自定义图片滤镜
  • 2026年3月建筑结构检测产品推荐,建筑结构检测/建筑加固/建筑结构胶,建筑结构检测公司推荐 - 品牌推荐师
  • Phi-3.5-Mini-Instruct真实案例:将‘做一个记账App’需求分解为MVP功能列表+优先级排序
  • 别死记74LS194A功能表!用Arduino+LED动态演示移位寄存器的4种工作模式
  • 别再只盯着PTB了!用WikiText-103训练你的第一个语言模型(附完整代码)
  • 戴尔笔记本风扇控制难题:如何平衡散热性能与运行噪音
  • Qwen3.5-2B赋能运维自动化:智能日志分析与故障预警
  • PDCCH Order:NR中触发随机接入的“调度指令”详解
  • VC8升级后必做的5项验证清单:除了看版本号,这些关键服务你检查了吗?
  • Youtu-VL-4B-Instruct源码部署:Windows WSL2环境下的GGUF模型运行与WebUI调试指南
  • RP2040微控制器驱动乐高积木运行Doom游戏
  • 题解:AtCoder AT_awc0001_d Merchant on the Highway
  • 老项目维护必备:在Windows Server 2022上完美部署SQL Server 2012全攻略
  • 想给孩子说的话(1):警惕成长路上的陷阱
  • 室内动捕+Position模式:为你的PX4无人机开启‘上帝视角’PID自整定
  • DeepL翻译浏览器扩展:让外语内容阅读变得轻松自然
  • WinUtil:终极Windows管理工具,让你的电脑从此告别繁琐设置