Python 为什么是collections.Counter比'';。计数
我有一个简单的任务:计算字符串中每个字母出现的次数。我使用了一个Python 为什么是collections.Counter比'';。计数,python,performance,counter,Python,Performance,Counter,我有一个简单的任务:计算字符串中每个字母出现的次数。我使用了一个计数器(),但在一个论坛上,我看到了使用dict()/计数器()比对每个字母使用string.count()慢得多的信息。我认为它只会在字符串中交互一次,而string.count()解决方案必须在字符串中迭代四次(在本例中)。为什么Counter()这么慢 >>> timeit.timeit('x.count("A");x.count("G");x.count("C");x.count("T")', setup=
计数器()
,但在一个论坛上,我看到了使用dict()
/计数器()
比对每个字母使用string.count()
慢得多的信息。我认为它只会在字符串中交互一次,而string.count()
解决方案必须在字符串中迭代四次(在本例中)。为什么Counter()
这么慢
>>> timeit.timeit('x.count("A");x.count("G");x.count("C");x.count("T")', setup="x='GAAAAAGTCGTAGGGTTCCTTCACTCGAGGAATGCTGCGACAGTAAAGGAGGCCACGTGGTTGAGAGTTCCTAAGCATTCGTATGTACACCCGGACTCGATGCACTCAAACGTGCTTAAGGGTAAAGAAGGTCGAGAGGTATACTGGGGCACTCCCCTTAGAATTATATCTTGGTCAACTACAATATGGATGGAAATTCTAAGCCGAAAACGACCCGCTAGCGGATTGTGTATGTATCACAACGGTTTCGGTTCATACGCAAAATCATCCCATTTCAAGGCCACTCAAGGACATGACGCCGTGCAACTCCGAGGACATCCCTCAGCGATTGATGCAACCTGGTCATCTAATAATCCTTAGAACGGATGTGCCCTCTACTGGGAGAGCCGGCTAGACTGGCATCTCGCGTTGTTCGTACGAGCTCCGGGCGCCCGGGCGGTGTACGTTGATGTACAGCCTAAGAGCTTTCCACCTATGCTACGAACTAATTTCCCGTCCATCGTTCCTCGGACTGAGGTCAAAGTAACCCGGAAGTACATGGATCAGATACACTCACAGTCCCCTTTAATGACTGAGCTGGACGCTATTGATTGCTTTATAAGTGTTATGGTGAACTCGAAGACTTAGCTAGGAATTTCGCTATACCCGGGTAATGAGCTTAATACCTCACAGCATGTACGCTCTGAATATATGTAGCGATGCTAGCGGAACGTAAGCGTGAGCGTTATGCAGGGCTCCGCACCTCGTGGCCACTCGCCCAATGCCCGAGTTTTTGAGCAATGCCATGCCCTCCAGGTGAAGCGTGCTGAATATGTTCCGCCTCCGCACACCTACCCTACGGGCCTTACGCCATAGCTGAGGATACGCGAGTTGGTTAGCGATTACGTCATTCCAGGTGGTCGTTC'", number=10000)
0.07911698750407936
>>> timeit.timeit('Counter(x)', setup="from collections import Counter;x='GAAAAAGTCGTAGGGTTCCTTCACTCGAGGAATGCTGCGACAGTAAAGGAGGCCACGTGGTTGAGAGTTCCTAAGCATTCGTATGTACACCCGGACTCGATGCACTCAAACGTGCTTAAGGGTAAAGAAGGTCGAGAGGTATACTGGGGCACTCCCCTTAGAATTATATCTTGGTCAACTACAATATGGATGGAAATTCTAAGCCGAAAACGACCCGCTAGCGGATTGTGTATGTATCACAACGGTTTCGGTTCATACGCAAAATCATCCCATTTCAAGGCCACTCAAGGACATGACGCCGTGCAACTCCGAGGACATCCCTCAGCGATTGATGCAACCTGGTCATCTAATAATCCTTAGAACGGATGTGCCCTCTACTGGGAGAGCCGGCTAGACTGGCATCTCGCGTTGTTCGTACGAGCTCCGGGCGCCCGGGCGGTGTACGTTGATGTACAGCCTAAGAGCTTTCCACCTATGCTACGAACTAATTTCCCGTCCATCGTTCCTCGGACTGAGGTCAAAGTAACCCGGAAGTACATGGATCAGATACACTCACAGTCCCCTTTAATGACTGAGCTGGACGCTATTGATTGCTTTATAAGTGTTATGGTGAACTCGAAGACTTAGCTAGGAATTTCGCTATACCCGGGTAATGAGCTTAATACCTCACAGCATGTACGCTCTGAATATATGTAGCGATGCTAGCGGAACGTAAGCGTGAGCGTTATGCAGGGCTCCGCACCTCGTGGCCACTCGCCCAATGCCCGAGTTTTTGAGCAATGCCATGCCCTCCAGGTGAAGCGTGCTGAATATGTTCCGCCTCCGCACACCTACCCTACGGGCCTTACGCCATAGCTGAGGATACGCGAGTTGGTTAGCGATTACGTCATTCCAGGTGGTCGTTC'", number=10000)
2.1727447831030844
>>> 2.1727447831030844 / 0.07911698750407936
27.462430656767047
>>>
计数器
类继承自dict
,而string.count
是以下C实现(CPython 3.3):
/*stringlib:count实现*/
#ifndef STRINGLIB\u FASTSEARCH\u
#在包含此模块之前,错误必须包含“stringlib/fastsearch.h”
#恩迪夫
Py_LOCAL_INLINE(Py_ssize_t)
STRINGLIB(计数)(常量STRINGLIB_CHAR*str,Py_ssize_t str_len,
常量STRINGLIB_CHAR*sub,Py_ssize_t sub_len,
Py_ssize_t最大计数)
{
Py_-ssize_-t计数;
如果(str_len<0)
返回0;/*start>len(str)*/
if(sub_len==0)
返回(str_len
猜猜看,哪一个更快?:) Counter()
允许您计算任何可散列对象,而不仅仅是子字符串。两种解决方案都是O(n)
-时间。您的测量结果表明,通过Counter()
对单个字符进行迭代和散列的开销大于运行s.count()
4次
Counter()
可以使用C helper来计算元素,但它似乎没有特殊情况的字符串,并且使用了适用于任何其他iterable的通用算法,即:
while(1){
key=PyIter_Next(it);
if(key==NULL)
打破
oldval=PyObject_GetItem(映射,键);
如果(oldval==NULL){
如果(!PyErr_发生()| |!PyErr_异常匹配(PyExc_KeyError))
打破
PyErr_Clear();
Py_增量(一个);
newval=1;
}否则{
newval=PyNumber\u Add(oldval,一);
Py_DECREF(oldval);
if(newval==NULL)
打破
}
if(PyObject_SetItem(映射、键、newval)=-1)
打破
Py_CLEAR(newval);
Py_DECREF(键);
}
将其与ByTestRing的开销进行比较:
(i=0;i
如果(s[i]==p[0]){
计数++;
if(count==maxcount)
返回最大计数;
}
返回计数;
它不是算法-x.count()
意味着你每检查一项循环一次,计数器()只循环一次。可能这种情况下的管理费用高于储蓄。相关:
/* stringlib: count implementation */
#ifndef STRINGLIB_FASTSEARCH_H
#error must include "stringlib/fastsearch.h" before including this module
#endif
Py_LOCAL_INLINE(Py_ssize_t)
STRINGLIB(count)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
Py_ssize_t maxcount)
{
Py_ssize_t count;
if (str_len < 0)
return 0; /* start > len(str) */
if (sub_len == 0)
return (str_len < maxcount) ? str_len + 1 : maxcount;
count = FASTSEARCH(str, str_len, sub, sub_len, maxcount, FAST_COUNT);
if (count < 0)
return 0; /* no match */
return count;
}