首页 > 编程语言 >19、Python之容器:快来数一数,24678?Counter能数得更好

19、Python之容器:快来数一数,24678?Counter能数得更好

时间:2024-07-24 11:57:34浏览次数:13  
标签:Python 能数 19 Counter 计数 哈希 print 统计

引言

关于数据的分组计数,前面的文章中已经涉及了很多次。眼下要进行分组计数,我们可用的方法有:
1、直接使用dict进行计数,需要对首次出现的键进行判断初始化的操作;
2、使用dict的setdefault()方法进行计数,代码可以简化一些,虽然方法名有点怪;
3、defaultdict进行计数,可以设置自动初始化,代码更加简洁。

虽然前面这三个方法都可以实现计数的需求,但是,还是停留在相对基础的计数功能。

如果我们想要更加灵活的计数功能,比如计完数之后,取出Top N,比如分别计数之后的合并……

前面的基础计数功能,倒不是不能实现这些需求,只是相对来说,有些麻烦了。我们可以试试collections中的Counter类,一个专门为计数而生的工具类。

Counter定义

Counter是collections模块下的一个工具类,我们已经介绍过的defaultdict也是该模块中的。
首先看下Counter的定义文档:


可以看到Counter是dict的子类,用于统计可哈希的元素的个数。其实,从文档中,已经能学到关于Counter的主要功能了。

需要注意的是,统计的是可哈希的元素,这点可能会限制了Coutner的使用范围,但是,结合defaultdict,还是可以实现更加灵活的计数。

要使用Counter,还要看下我们怎么能够构造一个Counter对象。看下文档中,魔术方法:__init__的说明:


可以看到,我们有几种主要的构造方式:
1、无参形式,直接构造一个空对象,然后在后续逐步更新。
2、传入一个可迭代的对象,一般是原始数据明细,比如字符串、列表、元组等,会自动对可迭代对象计数。
3、传入一个字典对象,一般是已经有的计数结果,用于对计数结果进行更进一步的扩充。
4、以关键字参数的形式传参,如同字典一样,只是已有的计数结果的存储形式可能不同而已。

所以,对于不可哈希的元素,我们可以通过dict或者defaultdict进行计数,然后用统计结果进行Counter对象的构造。

Counter的核心用法

1、简单的可哈希数据元素的计数并取出Top N

首先我们以单词计数为例,首先我们先生成一个列表,存放各个单词,然后对这些单词进行统计计数,最终输出单词的统计结果,并给出出现最多的Top 3。

直接看代码:

from collections import Counter
import random

# 生成测试数据
words = [random.choice(['Python', 'Java', 'C++', 'Rust', 'Go', 'Ruby', 'Swift', 'Lua']) for _ in range(1000)]

# 构造Counter计数器
c = Counter(words)
# 输出统计结果
print(c)
# 获取Python的出现次数
print(c['Python'])
# 获取Top 3
print(c.most_common(3))

执行结果:

代码中,我们使用list存放所有的单词数据,然后用其构造一个Counter对象。
Counter对象可以像dict一样,使用[key]方式索引元素的出现次数。
most_common(n)方法,以列表的形式,返回Top n的数据,列表中的元素为元组形式,分别为键值和对应的次数。

复杂的计数场景

有些场景下,计数结果并没有我们所看到的这么简单。

如果数据存储在了两个列表中,或者数据量比较大,我们是分布式统计的,以便于提高统计的效率,就会涉及到每个局部统计的结果合并的问题。

如果使用dict或者defaultdict来处理这种情况,可能又涉及到键值判断或者初始化默认值的情况,但是用Counter则会变得简单很多,可以直接进行两个Counter的数学运算。

2、Counter对象的增量迭代式计数

首先看,增量式统计,数据是一批批陆续到来的,我们要使用Counter的update()方法进行计数的增量更新:

from collections import Counter

# 第一批测试数据
words1 = ['Python'] * 10
words1.extend(['Java'] * 5)
# 构造计数器对象
c = Counter(words1)
# 输出当前统计结果
print(c)

# 等待一段时间,第二批数据来了
words2 = ['Python', 'Java', 'C++', 'Rust']
# 更新计数
c.update(words2)
print(c)

3、Counter对象的数学运算,实现局部计数结果的合并

大数据计算中,一个典型的入门案例,就是分布式word count。将海量数据切分为多个任务,分布到不同节点上分别进行统计,获取中间结果,然后将结合汇聚,生成最终的结果。

我们简单模拟一下,只是为了演示Counter的数学运算:

from collections import Counter

# 假如数据量比较大,可能需要拆分成多个子任务,并行
# 统计子任务1
words1 = ['Python'] * 10
words1.extend(['Java'] * 5)
# 构造计数器对象
c1 = Counter(words1)
# 输出当前统计结果
print(c1)

# 统计子任务2
words2 = ['Python', 'Java', 'C++', 'Rust']
c2 = Counter(words2)
print(c2)

# 合并获取最终结果
c = c1 + c2
print(c)

执行结果:

当然,Coutner也是支持减法、交集、并集等运算的,这里就不一一演示了,感兴趣的,可以自行尝试。

4、不可哈希元素计数
针对不可哈希的元素的统计计数,我们可以结合dict、defaultdict得出统计结果,如果后续需要进行Top N的处理,或者统计结果的合并,再交由Counter进行进一步加工处理。

也可以使用列表生成式,将不可哈希的元素转换为可哈希的元素,然后进行统计。

总结

本文主要就关于统计计数的相关实现方式,重点介绍了Counter的基本使用。其实,这些都不需要记忆,只要有需求场景时,能想到有这么个工具类,实际使用时,再查看定义文档即可。

标签:Python,能数,19,Counter,计数,哈希,print,统计
From: https://blog.csdn.net/dqrcsc/article/details/140598921

相关文章

  • Codeforces 1987C
    codeforcesP1987C给定一个n长度的数组,每一步都要遍历整个数组。如果某个元素是末尾元素或是比其后一个元素大,则该元素减去1直到该元素为0,求解总步数,算法复杂度要求\(O(n)\)先给出暴力解法,复杂度\(O(n^2)\): intt=0; do{ for(inti=0;i<n-1;i++){ if(a[i]......
  • [极客大挑战 2019]BuyFlag
    [极客大挑战2019]BuyFlag源代码的提示<!-- ~~~postmoneyandpassword~~~if(isset($_POST['password'])){ $password=$_POST['password']; if(is_numeric($password)){ echo"passwordcan'tbenumber</br>"; }elseif($p......
  • 记录一下oracle 19c的集群节点移除、新增操作
    虽然掌握得不够深入,但越来越讨厌oracle数据库这个软件了,实在不愿意再孤岛这个笨重、复杂的oracle了。今天花了好几个小时操作一个实验环境的迁移、配置,记录几个步骤吧,也许后续会有用。■查看数据库配置信息[oracle@node1:0~]$srvctlconfigdatabase-dblikingdbDatabaseu......
  • 代码随想录算法训练营第四天 | Leetcode 24 两两交换链表中的节点 Leetcode 19 删除链
    前言今天链表的内容突出一个注意细节,判空条件,头节点是否为空等等。采用虚拟头节点可以方便链表进行更改,还需要学会使用临时变量。 Leetcode24两两交换链表中的节点题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/代码随想录题解:代码随想录(programmercarl.......
  • Mac ml-agents release 19(v0
    Macml-agentsrelease19(v0.28.0)踩雷主要参考这篇博客:ML-Agents在MacM1上的安装跟着这篇安装完,在激活虚拟环境的终端输入mlagents-learn检验,如果正常应输出如下:后面超时报错不用管,因为还没在unity中启动训练环境。但是在跟完这篇博客后我这里并未成功执行此命令,报了几......
  • SQL2019收缩LDF的日志文件
    解决日志文件满造成SQL数据库无法写入文件问题1、打开MicrosoftSQLServerManagementStudio管理工具,右键你要压缩的数据库->任务->收缩->文件2、在“文件类型”选择“日志”,在“收缩操作”选择“在释放未使用的空间前重新组织页”,这里会给出一个允许收缩到的最小M数......
  • CF1990F Polygonal Segments 题解
    题目链接:https://codeforces.com/contest/1990/problem/F赛时想到了一个略显抽象的做法,但因为写反了一个判断导致没能过掉。赛后调参卡过,用时\(3.5/8\)秒。为了不丢失这个idea最终还是决定写个题解记录一下。题意简述给定一个数组\(a_{1..n}\),执行以下查询:查询区间\([......
  • VMware Tanzu Kubernetes Grid Integrated Edition (TKGI) 1.19.1 - 运营商 Kubernete
    VMwareTanzuKubernetesGridIntegratedEdition(TKGI)1.19.1-运营商Kubernetes解决方案Kubernetes-basedcontainersolutionwithadvancednetworking,aprivatecontainerregistry,andlifecyclemanagement请访问原文链接:https://sysin.org/blog/vmware-tkgi/,......
  • 题解:CF1992F Valuable Cards
    Part1:前言题目翻译在他最喜欢的咖啡馆里,Kmes再次想尝尝皮草大衣下的鲱鱼。以前,这对他来说并不难,但咖啡馆最近推出了一项新的购买政策。现在,为了进行购买,Kmes需要解决以下问题:在他面前摆放着\(n\)张不同价格的卡,第\(i\)张卡的价格为\(a_i\),在这些价格中没有整数\(x\)。K......
  • P1991 无线通讯网
    原题链接题解首先,考虑如何分配卫星电话使得\(D\)最小是比较困难的,所以我们考虑怎样的D可以使得卫星电话个数不小于联通块个数由于D越小,联通块个数也就越小,所以具有单调性,考虑二分优化:最后的答案,一定是所有连通块内部,距离最长的树边(即失去该边之后,联通块变得不连通),由此......