python必背函数入门(Python标准库精华:collections.Counter)
python必背函数入门(Python标准库精华:collections.Counter)我再为你提供另一个解决方案,那就是更多地使用 Counter 魔法。我还将用函数的方法替换 for 循环,这样一来 for 循环就不是非要不可:-)这里有一个经验法则: 当你看到 defaultdict(int) 时,你可以用一个Counter 替换它。它可以做 defaultdict 所能做的一切,加上一些方便的技巧,比如 .most_common 方法,我们可以使用它来代替前面示例中笨拙的 max 表达式。通常的方法是使用类似于字典的结构,它将模式作为键保存,并计算模式在源数据库中出现的频率,因此结果有点类似于这样:(不要介意数字,这是一个小数据库!)据我所知,在这种情况下 人们通常会使用defaultdict。它在第一次访问时会自动初始化不存在的键值,你每次只需要执行result[key] = 1 即可。在我们的例子中,我们需要一个更复杂的东西: 一个defaultdict 用于存
这里有个好玩的问题。给定一个不同国家的电话号码库,确定每个国家中最普遍的显示格式,并使用它重新格式化这个国家的任意电话号码。例如,如果我们的数据语料库中的大多数美国电话号码都写成xxx-xxx -xxxx,那么字符串(206)1234567就应该转换为206-123-4567。
为了简单起见,我们假设所有的电话号码都是不包含国别前缀的。
转换
实际的转换并不是这篇文章的主题,但是为了完整起见,这里有两个补充的函数,一个确定模式,另一个根据模式格式化电话号码:
(为了清晰起见省略了错误处理。)
简单的解决方案
通常的方法是使用类似于字典的结构,它将模式作为键保存,并计算模式在源数据库中出现的频率,因此结果有点类似于这样:
(不要介意数字,这是一个小数据库!)
据我所知,在这种情况下 人们通常会使用defaultdict。它在第一次访问时会自动初始化不存在的键值,你每次只需要执行result[key] = 1 即可。在我们的例子中,我们需要一个更复杂的东西: 一个defaultdict 用于存储country,它将使用嵌套的defaultdict 来初始化计数的键。总的来说它看起来可能是这样的:
Counter(计数器)
这里有一个经验法则: 当你看到 defaultdict(int) 时,你可以用一个Counter 替换它。它可以做 defaultdict 所能做的一切,加上一些方便的技巧,比如 .most_common 方法,我们可以使用它来代替前面示例中笨拙的 max 表达式。
平铺和函数
我再为你提供另一个解决方案,那就是更多地使用 Counter 魔法。我还将用函数的方法替换 for 循环,这样一来 for 循环就不是非要不可:-)
下面是代码,然后是解释:
看吧,没有循环了!
让我来解释一下这里发生的一切。
-
事实上,Counter 可以处理一个平铺式序列的东西,然后一口气数完:
在我们的例子中,要想实现这一点,我们必须用平面数据结构替换嵌套数据结构。这可以通过简单地将键值粘合在一个元组中, 并用等效的 stats[(country pattern)] 替换 stats[country][ pattern] (你可以对任意数量的键执行此操作)来实现。
-
表达式(country get_pattern(phone)) for country phone in db 看起来像一个没有方括号的列表推导。实际上,它是一个生成器表达式,你可以遍历它而不需要在内存中构造一个实际的列表。它通常用括号括起来( ... ),但是当它是一个函数调用中的唯一参数时,你可以省略它们,并避免使用像 Counter((..)) 这样丑陋的重复。
-
stats.most_common 在没有参数的情况下会将结构的全部内容作为一个排好序的 (key count) 列表返回:
它是按计数排序的,不考虑country,但是我们不关心这个,你稍后会看到这些,以及为什么我们需要反转它。
-
最后的表达式是一个字典推导,它遍历已排序的列表,使用(country pattern),_ 模拟一个键对的结构,将列表中嵌套的键对分解为单个变量。_ 是我们不使用的东西的惯例名称,在我们的例子中就是count。因此,我们实际转换成的最终字典序列是这样的,country变成键,模式变成值:
-
重要的是:具有相同键的后续值会替换字典中已经存在的值。这就是为什么我们需要反转列表的原因,所以我们就用计数较大的模式替换最不常见的模式。这也是为什么我们不关心country之间的混合,因为它们不会相互影响。
诚然,最后一点是最不明显的。
这是不是更好一点?
我并不在乎,你可以自己判断:-) 我只是想实际的展示一下collections.Counter!
工作代码作为福利送给你: phone-counter.py(http://softwaremaniacs.org/media/blog/phone-counter.py)。
英文原文:http://softwaremaniacs.org/blog/2019/03/09/collections-counter/en/译者:忧郁的红秋裤