1271

How do I count the number of occurrences of a character in a string?

e.g. 'a' appears in 'Mary had a little lamb' 4 times.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Mat
  • 82,161
  • 34
  • 89
  • 109
  • To cross check the results based on the top answer below, you can also [use this tool](https://magictools.dev/#!/tools/character-occurences) – WJA Jan 02 '22 at 22:10
  • You might find the simplest way to code it but at the end, time complexity remains the same ,whether we use loops or built in count() . – Makarand Jan 03 '22 at 05:58

26 Answers26

1748

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

Return the number of non-overlapping occurrences of substring sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation.

>>> sentence = 'Mary had a little lamb'
>>> sentence.count('a')
4
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Ogre Codes
  • 18,693
  • 1
  • 17
  • 24
  • 2
    although you may want remove case-dependency with `sentence.lower().count('a')` – RufusVS Mar 24 '22 at 18:52
  • @RufusVS Just to mention, that doesn't work for all writing systems. For a more thorough approach, see [Veedrac's answer](/a/29247821/4518341) on "How do I do a case-insensitive string comparison?" – wjandrea Apr 17 '22 at 21:00
187

You can use .count() :

>>> 'Mary had a little lamb'.count('a')
4
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
eduffy
  • 39,140
  • 13
  • 95
  • 92
139

To get the counts of all letters, use collections.Counter:

>>> from collections import Counter
>>> counter = Counter("Mary had a little lamb")
>>> counter['a']
4
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Brenden Brown
  • 3,125
  • 1
  • 14
  • 15
  • 20
    Why is this better when used frequently? What is the advantage? – meshy Feb 10 '15 at 22:36
  • 27
    If you want the counts for a lot of the letters in a given string, Counter provides them all in a more succinct form. If you want the count for one letter from a lot of different strings, Counter provides no benefit. – Brenden Brown Feb 17 '15 at 19:30
  • 2
    For this particular instance, counting characters, I would prefer collections.counter. For finding instances of a specific substring, I would use a regular expression or the str.count() method. I haven't tested, but there may be a performance difference due to a slight overhead in counting all characters and appending to a dictionary rather than counting occurrences of a single substring. I would suggest writing a script to generate a very long file to search and then timing execution of each method. – Daniel B. Jul 20 '15 at 17:58
  • 5
    The advantage when used frequently is that Counter calculates all the counts ONE TIME, which is almost as fast as doing mystring.count('a') one time. Thus, if you do this 20 times, you are saving maybe 10 times the computation time. Counter also can tell you if an item is in the string: for example, if 'a' in counter: – BAMF4bacon May 31 '16 at 14:32
63

Regular expressions maybe?

import re
my_string = "Mary had a little lamb"
len(re.findall("a", my_string))
Sinan Taifour
  • 10,521
  • 3
  • 33
  • 30
  • 33
    A fine idea, but overkill in this case. The string method 'count' does the same thing with the added bonus of being immediately obvious about what it is doing. – nilamo Jul 20 '09 at 20:18
  • 20
    why negative rate, maybe someone needs this kind of code for something similar. my vote up – kiltek Mar 31 '12 at 10:18
  • 17
    This should be downvoted because it is the least efficient way possible to count characters in a string. If the goal is simply to count characters, as the question indicates, it would be hard to find a worse way to do the job. In terms of memory and processor overhead, this solution is definitely to be avoided. No one will ever "need" to use this method to find the count of characters in a string. – Christopher Oct 21 '13 at 18:04
  • good solution when string methods are not available: `len(re.findall('1',bin(10)))` – Conor Jun 23 '16 at 08:48
  • @Conor When are string methods not available? Why not just `bin(10).count('1')`? – Brian Oct 20 '21 at 17:43
  • In my case I needed to match two or more line break characters`\n\n` to distinguish paragraphs and this worked great using `len(re.findall(r"(\n){2,}", x))` – abk Aug 02 '22 at 03:14
37

Python-3.x:

"aabc".count("a")

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

Return the number of non-overlapping occurrences of substring sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation.

tremendows
  • 4,262
  • 3
  • 34
  • 51
Aaron Fi
  • 10,116
  • 13
  • 66
  • 91
34
myString.count('a');

more info here

Finer Recliner
  • 1,579
  • 1
  • 13
  • 21
19

str.count(a) is the best solution to count a single character in a string. But if you need to count more characters you would have to read the whole string as many times as characters you want to count.

A better approach for this job would be:

from collections import defaultdict

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

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

So you'll have a dict that returns the number of occurrences of every letter in the string and 0 if it isn't present.

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

For a case insensitive counter you could override the mutator and accessor methods by subclassing defaultdict (base class' ones are read-only):

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
Nuno André
  • 4,739
  • 1
  • 33
  • 46
18

This easy and straightforward function might help:

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}

If a comprehension is desired:

def check_freq(x):
    return {c: x.count(c) for c in set(x)}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Erick Mwazonga
  • 1,020
  • 12
  • 25
12

Regular expressions are very useful if you want case-insensitivity (and of course all the power of regex).

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))

Be aware that the regex version takes on the order of ten times as long to run, which will likely be an issue only if my_string is tremendously long, or the code is inside a deep loop.

jafelds
  • 894
  • 8
  • 12
  • 2
    Regex is overkill if you are just trying to fix case sensitivity. my_sting.lower().count('m') is more performant, more clear, and more succinct. – Ogre Codes Aug 17 '16 at 05:31
6
a = 'have a nice day'
symbol = 'abcdefghijklmnopqrstuvwxyz'
for key in symbol:
    print(key, a.count(key))
questionto42
  • 7,175
  • 4
  • 57
  • 90
rookie
  • 61
  • 1
  • 1
6

I don't know about 'simplest' but simple comprehension could do:

>>> my_string = "Mary had a little lamb"
>>> sum(char == 'a' for char in my_string)
4

Taking advantage of built-in sum, generator comprehension and fact that bool is subclass of integer: how may times character is equal to 'a'.

Aivar Paalberg
  • 4,645
  • 4
  • 16
  • 17
5

I am a fan of the pandas library, in particular the value_counts() method. You could use it to count the occurrence of each character in your string:

>>> import pandas as pd
>>> phrase = "I love the pandas library and its `value_counts()` method"
>>> pd.Series(list(phrase)).value_counts()
     8
a    5
e    4
t    4
o    3
n    3
s    3
d    3
l    3
u    2
i    2
r    2
v    2
`    2
h    2
p    1
b    1
I    1
m    1
(    1
y    1
_    1
)    1
c    1
dtype: int64
4

count is definitely the most concise and efficient way of counting the occurrence of a character in a string but I tried to come up with a solution using lambda, something like this:

sentence = 'Mary had a little lamb'
sum(map(lambda x : 1 if 'a' in x else 0, sentence))

This will result in:

4

Also, there is one more advantage to this is if the sentence is a list of sub-strings containing same characters as above, then also this gives the correct result because of the use of in. Have a look:

sentence = ['M', 'ar', 'y', 'had', 'a', 'little', 'l', 'am', 'b']
sum(map(lambda x : 1 if 'a' in x else 0, sentence))

This also results in:

4

But of course this will work only when checking occurrence of single character such as 'a' in this particular case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Satish Prakash Garg
  • 2,213
  • 2
  • 16
  • 25
4

An alternative way to get all the character counts without using Counter(), count and regex

counts_dict = {}
for c in list(sentence):
  if c not in counts_dict:
    counts_dict[c] = 0
  counts_dict[c] += 1

for key, value in counts_dict.items():
    print(key, value)
Syed Shamikh Shabbir
  • 1,252
  • 1
  • 14
  • 18
3
a = "I walked today,"
c=['d','e','f']
count=0
for i in a:
    if str(i) in c:
        count+=1

print(count)
Kquek
  • 57
  • 4
  • This does not differentiate the counts for d, e, f. – Gino Mempin Sep 29 '20 at 04:30
  • Hi @GinoMempin don't think the intention here is to differentiate however you may declare two other variables and compare i to 'd','e' and 'f' separately if you wish to do so. – Kquek Sep 29 '20 at 08:11
3

I know the ask is to count a particular letter. I am writing here generic code without using any method.

sentence1 =" Mary had a little lamb"
count = {}
for i in sentence1:
    if i in count:
        count[i.lower()] = count[i.lower()] + 1
    else:
        count[i.lower()] = 1
print(count)

output

{' ': 5, 'm': 2, 'a': 4, 'r': 1, 'y': 1, 'h': 1, 'd': 1, 'l': 3, 'i': 1, 't': 2, 'e': 1, 'b': 1}

Now if you want any particular letter frequency, you can print like below.

print(count['m'])
2
LOrD_ARaGOrN
  • 3,884
  • 3
  • 27
  • 49
3

the easiest way is to code in one line:

'Mary had a little lamb'.count("a")

but if you want can use this too:

sentence ='Mary had a little lamb'
   count=0;
    for letter in sentence :
        if letter=="a":
            count+=1
    print (count)
  • Twenty-two answers. The top answer has more upvotes than I’ve received in total over eight years on Stack Overflow. Why do you prefer this solution? What is it contributing that the existing answers are missing? – Jeremy Caney Dec 21 '21 at 17:43
  • No one mentioned a class method in python. which is the easiest and shortest way – fsafarkhani Dec 22 '21 at 12:26
  • Now, I see they mentioned it! It is ok I just wanted to show my code too. I think no one mentioned it – fsafarkhani Dec 22 '21 at 12:34
2

Python 3

Ther are two ways to achieve this:

1) With built-in function count()

sentence = 'Mary had a little lamb'
print(sentence.count('a'))`

2) Without using a function

sentence = 'Mary had a little lamb'    
count = 0

for i in sentence:
    if i == "a":
        count = count + 1

print(count)
Dipen Gajjar
  • 1,338
  • 14
  • 23
2

To find the occurrence of characters in a sentence you may use the below code

Firstly, I have taken out the unique characters from the sentence and then I counted the occurrence of each character in the sentence these includes the occurrence of blank space too.

ab = set("Mary had a little lamb")

test_str = "Mary had a little lamb"

for i in ab:
  counter = test_str.count(i)
  if i == ' ':
    i = 'Space'
  print(counter, i)

Output of the above code is below.

1 : r ,
1 : h ,
1 : e ,
1 : M ,
4 : a ,
1 : b ,
1 : d ,
2 : t ,
3 : l ,
1 : i ,
4 : Space ,
1 : y ,
1 : m ,
  • Downvote. Duplicate of https://stackoverflow.com/a/49385352/11154841, it only makes the unneeded way over `''.join()`. – questionto42 Dec 29 '21 at 20:01
  • @-questionto42 may you please elaborate the duplication meaning here stated by you but I agreed with your point over use of join and i am removing the same. Thank you! – Shreyansh Dwivedi Jan 03 '22 at 05:37
  • The other answer was first and also has a `set()` of a string in it that it loops over to check the `count()` of each letter in the set. It adds the results to keys of a dictionary and prints the dictionary afterwards instead of this answer that prints the counts directly during the loop (how the results are printed is not the main idea anyway). Therefore the duplicate. – questionto42 Jan 03 '22 at 17:59
  • 1
    @questionto42 The concept can be used by anyone and the same idea may come into different mind but when you say the answer is duplicate I say it is not as I have gone through that stackoverflow that you mention in the comment and there is a difference in that answer and mine there space character is not been calculated and in my answer it is been calculated so its not a duplicate as duplicate means each and everything should be exactly same. please make a note on this and if you find this explanation correct than you may remove your down vote. – Shreyansh Dwivedi Jan 04 '22 at 10:47
  • 1
    I had a look at it. The other solution gives you a dictionary with a `' '` as the key and the number of `' '` as the value. You can rename a key of a dictionary as you like using `pop`, in this case `' '` to `space`, this does not add value. I still withdraw my downvote since someone might want to have a solution without a dictionary. Yet, this is a duplicate, the main trick is just the `set()` and the `count()`, which you repeat. – questionto42 Jan 04 '22 at 21:15
2

Use count:

sentence = 'A man walked up to a door'
print(sentence.count('a'))
# 4
Pythoneer
  • 319
  • 1
  • 16
1

"Without using count to find you want character in string" method.

import re

def count(s, ch):

   pass

def main():

   s = raw_input ("Enter strings what you like, for example, 'welcome': ")  

   ch = raw_input ("Enter you want count characters, but best result to find one character: " )

   print ( len (re.findall ( ch, s ) ) )

main()
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
B-Y
  • 187
  • 1
  • 2
  • 12
  • 10
    Why the empty count function? Why the main() function? Why the ugly spaces everywhere? This is NOT a good answer. – bugmenot123 Aug 09 '17 at 08:04
1

This is an extension of the accepted answer, should you look for the count of all the characters in the text.

# Objective: we will only count for non-empty characters

text = "count a character occurrence"
unique_letters = set(text)
result = dict((x, text.count(x)) for x in unique_letters if x.strip())

print(result)
# {'a': 3, 'c': 6, 'e': 3, 'u': 2, 'n': 2, 't': 2, 'r': 3, 'h': 1, 'o': 2}
CypherX
  • 7,019
  • 3
  • 25
  • 37
Thiru G
  • 45
  • 3
  • Downvote. Duplicate of https://stackoverflow.com/a/49385352/11154841, and the set of a list is not needed, you can directly use the set() on the string to get the unique characters. – questionto42 Dec 29 '21 at 19:52
  • Too many red flags are in this answer! Why are you overwriting `str` and setting that to a string? `str` is a standard module in core python. Please check the `builtins` in python and NEVER overwrite them with some other value. The question asked for counting the number of occurrences for each character. Where is your answer that counts and presents that in a suitable data sctructure (a `List[tuple]`, or a `Dict[str, int]`)? Also, you are using variable names with capital letters. Please only use snake-case and don't use capitalized variable names unless they are meant to be constants. – CypherX Nov 13 '22 at 20:42
0

Taking up a comment of this user:

import numpy as np
sample = 'samplestring'
np.unique(list(sample), return_counts=True)

Out:

(array(['a', 'e', 'g', 'i', 'l', 'm', 'n', 'p', 'r', 's', 't'], dtype='<U1'),
 array([1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1]))

Check 's'. You can filter this tuple of two arrays as follows:

a[1][a[0]=='s']

Side-note: It works like Counter() of the collections package, just in numpy, which you often import anyway. You could as well count the unique words in a list of words instead.

questionto42
  • 7,175
  • 4
  • 57
  • 90
-1

No more than this IMHO - you can add the upper or lower methods

def count_letter_in_str(string,letter):
    return string.count(letter)
Tim Seed
  • 5,119
  • 2
  • 30
  • 26
  • This may lead to "`error CS1061: 'string' does not contain a definition for 'count' and no accessible extension method 'count' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)`". – Peter Mortensen Jul 08 '23 at 23:08
-1

You can use loop and dictionary.

def count_letter(text):
    result = {}
    for letter in text:
        if letter not in result:
            result[letter] = 0
        result[letter] += 1
    return result
blackbishop
  • 30,945
  • 11
  • 55
  • 76
-2
spam = 'have a nice day'
var = 'd'


def count(spam, var):
    found = 0
    for key in spam:
        if key == var:
            found += 1
    return found
count(spam, var)
print 'count %s is: %s ' %(var, count(spam, var))
poolie
  • 9,289
  • 1
  • 47
  • 74
rookie
  • 1