在一个字符串中计算一个字符出现的次数。

1286

如何统计字符串中某个字符出现的次数?

例如,在字符串“Mary had a little lamb”中,“a”出现了4次。


为了交叉检查基于下面的最佳答案的结果,您还可以使用此工具。 - WJA
你可能会找到编码的最简单方法,但最终,无论我们使用循环还是内置的count()函数,时间复杂度仍然保持不变。 - Makarand
26个回答

1768

str.count(sub[, start[, end]])

返回字符串中在区间 [start, end] 中非重叠出现的子字符串 sub 的数量。可选参数 startend 的解释方式与切片相同。

>>> sentence = 'Mary had a little lamb'
>>> sentence.count('a')
4

2
尽管您可能希望使用 sentence.lower().count('a') 来消除大小写敏感性。 - RufusVS
@RufusVS 只是提一下,这并不适用于所有的书写系统。如果想要更全面的方法,请参考“如何进行大小写不敏感的字符串比较?”中 Veedrac 的回答 - wjandrea

189
你可以使用 .count() 方法:
>>> 'Mary had a little lamb'.count('a')
4

141

要获取所有字母的计数,请使用collections.Counter

>>> from collections import Counter
>>> counter = Counter("Mary had a little lamb")
>>> counter['a']
4

20
为什么经常使用会更好?有什么优势? - meshy
27
如果您想要得到给定字符串中许多字母的计数,Counter可以以更简洁的形式提供。如果您想要从许多不同的字符串中获得一个字母的计数,则Counter没有任何好处。 - Brenden Brown
2
对于这个特定的实例,计算字符,我更喜欢使用collections.counter。对于查找特定子字符串的实例,我会使用正则表达式或str.count()方法。我没有测试过,但由于计算所有字符并将其附加到字典中而不是计算单个子字符串的出现次数,可能会存在性能差异。我建议编写一个脚本来生成一个非常长的文件进行搜索,然后计时执行每种方法。 - Daniel B.
6
如果经常使用Counter,其优点在于它只需计算一次所有计数,几乎与一次性执行mystring.count('a')的速度相当。 因此,如果您这样做20次,您将节省大约10倍的计算时间。 Counter还可以告诉您字符串中是否存在某个项:例如,如果'a'在计数器中: - BAMF4bacon

63

也许需要用正则表达式?

import re
my_string = "Mary had a little lamb"
len(re.findall("a", my_string))

34
一个好主意,但在这种情况下有些过头了。字符串方法“count”可以做同样的事情,并且还有一个额外的好处,就是它立即清楚地表明了它正在做什么。 - nilamo
20
为什么要负利率,也许有人需要类似的代码。我点赞。 - kiltek
18
这篇文章应该被点踩,因为它是一种最低效的计算字符串中字符数量的方法。如果目标只是简单地计算字符数量,就像问题所示,那么很难找到比这更糟糕的方法。就内存和处理器开销而言,绝对要避免使用这种解决方案。没有人会真正“需要”使用这种方法来找出字符串中字符的计数。 - Christopher
当字符串方法不可用时,好的解决方案是:len(re.findall('1',bin(10))) - Conor
@Conor 什么时候字符串方法不可用?为什么不直接使用 bin(10).count('1') - Brian
在我的情况下,我需要匹配两个或多个换行符\n\n以区分段落,并且使用len(re.findall(r"(\n){2,}", x))非常有效。 - abk

37

Python-3.x:

"aabc".count("a")

str.count(sub[, start[, end]])

统计字符串中从指定起始位置到结束位置之间(包括起始位置但不包括结束位置)子串 sub 的不重叠出现次数。可选参数 start 和 end 的解释与切片表示法相同。


1
接受的答案应该更新为这个。 - WestCoastProjects

34

19

str.count(a) 是在字符串中计算单个字符数量的最佳解决方案。但如果您需要计算更多的字符,您需要将整个字符串读取多次,次数与您想要计算的字符数量相同。

这项工作的更好方法是:

from collections import defaultdict

text = 'Mary had a little lamb'
chars = defaultdict(int)

for char in text:
    chars[char] += 1

所以你将拥有一个字典,它返回字符串中每个字母出现的次数,如果不存在,则为0

>>>chars['a']
4
>>>chars['x']
0
为实现不区分大小写的计数器,您可以通过继承defaultdict(基类的方法只读)并覆盖其修改器和访问器方法来实现:
class CICounter(defaultdict):
    def __getitem__(self, k):
        return super().__getitem__(k.lower())

    def __setitem__(self, k, v):
        super().__setitem__(k.lower(), v)


chars = CICounter(int)

for char in text:
    chars[char] += 1

>>>chars['a']
4
>>>chars['M']
2
>>>chars['x']
0

你基本上是在重新实现Counter,而这已经是collections中的一个类了。 - merv
@merv 不完全是这样。Counter 是一个更加臃肿的纯 Python 类,而 defaultdict__missing__ 方法是用 C 写的。对于像这样简单的任务(int 也是用 C 实现的),这种方法略微更快一些。 - Nuno André
1
此外,np.unique(sample, return_counts=True) 可能会有用。 - TopCoder2000

18
这个简单明了的函数可能会有所帮助:
def check_freq(x):
    freq = {}
    for c in set(x):
       freq[c] = x.count(c)
    return freq

check_freq("abbabcbdbabdbdbabababcbcbab")
{'a': 7, 'b': 14, 'c': 3, 'd': 3}

如果需要理解:
def check_freq(x):
    return {c: x.count(c) for c in set(x)}

12

如果你想要不区分大小写的匹配(当然还有所有正则表达式的强大功能),那么正则表达式非常有用。

my_string = "Mary had a little lamb"
# simplest solution, using count, is case-sensitive
my_string.count("m")   # yields 1
import re
# case-sensitive with regex
len(re.findall("m", my_string))
# three ways to get case insensitivity - all yield 2
len(re.findall("(?i)m", my_string))
len(re.findall("m|M", my_string))
len(re.findall(re.compile("m",re.IGNORECASE), my_string))

请注意,正则表达式版本的运行时间大约需要原始版本的十倍,这可能只会在my_string非常长或代码位于深层循环中时成为问题。


3
如果你只是想解决大小写问题,正则表达式有些过头了。使用 my_string.lower().count('m') 更高效、更清晰、更简洁。 - Ogre Codes

6
a = 'have a nice day'
symbol = 'abcdefghijklmnopqrstuvwxyz'
for key in symbol:
    print(key, a.count(key))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接