计算字符串中给定子字符串的出现次数


201

如何计算给定子字符串在Python字符串中出现的次数?

例如:

>>> 'foo bar foo'.numberOfOccurrences('foo')
2

“子串数”是什么意思?子串的位置?子字符串出现多少次?还有吗
GreenMatt 2012年

2
这是家庭作业吗?如果是这样,请在您的问题中添加标签“家庭作业”。另外,您的问题不是很清楚。我会回答您似乎要问的问题,但我怀疑您确实想发现其他问题。
Jim DeLaHunt 2012年

在前面的评论之后,您可能想看一下:python:如何在另一个字符串中查找子字符串,或者如何在一个字符串(python)中找到子字符串的基本索引重复出现。由于这似乎是其中之一的重复,因此我投票关闭。
GreenMatt 2012年

@JimDeLaHunt有关记录,在cscircles.cemc.uwaterloo.ca/8-remix中有一个关于此的练习 -请参阅编码练习:子字符串计数
Nikos Alexandris

Answers:


334

string.count(substring), 像:

>>> "abcdabcva".count("ab")
2

更新:

正如评论中指出的那样,这是解决问题的方法 非重叠事件进行处理的方法。如果您需要计算重叠出现的次数,则最好在以下位置查看答案:“ Python regex找到所有重叠的匹配吗? ”,或者只是在下面检查我的其他答案。


14
那怎么办:"GCAAAAAG".count("AAA")哪个给出1,而正确答案是3?
漫画家

12
count显然是针对不重叠的比赛-这通常是人们想要做的。stackoverflow.com/questions/5616822/…处理重叠的匹配-但一个简单的,甚至昂贵的表达式是:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno 2015年

是否可以一次计算/搜索多个单词?like string.count(substring1,substring2)
Sushant Kulkarni

@SushantKulkarni号虽然有做这样的事的一个合乎逻辑的方式:string.count(substring1) + string.count(substring2)。但是请记住,如果有很多子字符串,这不是一种有效的方法,因为对每个子字符串进行计数需要对主字符串进行迭代。
Faheel

@SushantKulkarni的执行''.join([substring1, substring2]).count(pattern)比上面建议的解决方案更有效。我使用timeit检查。
恩里克·卡拉布格


19

根据您的实际意思,我提出以下解决方案:

  1. 您的意思是用空格分隔的子字符串的列表,并且想知道所有子字符串中的子字符串位置编号是什么:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. 您的意思是字符串中子字符串的字符位置:

    s.find('sub2')
    >>> 5
  3. 您的意思是su-bstring的出现次数(不重叠):

    s.count('sub2')
    >>> 1
    s.count('sub')
    >>> 3

尝试查找“ sub”或“ su”
obohovyk

我猜你的意思是s.find("su"),想知道你为什么得到0?嗯,这是子字符串的第一个指标"su"s。尝试"ub",您将得到1,尝试例如"z",您将获得-1,但找不到子字符串。
唐提问

我的意思是,您总是只找到第一个索引,而不是所有索引,@ arun-kumar-khattri提供了正确的答案
obohovyk

@ arun-kumar-khattri给出了您正在寻找的“正确”答案,我感到放心。也许您应该再看看jsbueno的注释,有时它们会回答您尚未问过的问题。
唐提问

就像第三种方法一样。顺便说一句,我想你应该提到它适用于不重叠的情况。
Zeinab Abbasimazar

12

在给定字符串中查找重叠子字符串的最佳方法是使用python正则表达式,它将使用正则表达式库查找所有重叠匹配项。这是怎么做的,左边是子字符串,右边是要匹配的字符串

print len(re.findall('(?=aa)','caaaab'))
3

2
也许您可以添加len(re.findall(f'(?= {sub_string})','caaaab'))来动态插入子字符串:)
Amresh Giri

10

要在Python 3中查找字符串中子字符串的重叠出现,此算法将执行以下操作:

def count_substring(string,sub_string):
    l=len(sub_string)
    count=0
    for i in range(len(string)-len(sub_string)+1):
        if(string[i:i+len(sub_string)] == sub_string ):      
            count+=1
    return count  

我本人检查了此算法,它起作用了。


1
小提示:您可以在诸如repl.it之类的在线服务上包含一个示例,并附上一些示例数据,而不必说“它是因为我检查了它而起作用” 。
Valentin

1
谢谢您的评论Valentin!这是我的第一个答案。我将从下一个答案中提高自己。
Bharath Kumar R

10

您可以使用两种方法对频率进行计数:

  1. 使用count()in str

    a.count(b)

  2. 或者,您可以使用:

    len(a.split(b))-1

其中a是字符串,b是要计算其频率的子字符串。


7

当前涉及方法的最佳答案count并不真正考虑重叠的出现,也不在乎空的子字符串。例如:

>>> a = 'caatatab'
>>> b = 'ata'
>>> print(a.count(b)) #overlapping
1
>>>print(a.count('')) #empty string
9

如果我们考虑重叠的子字符串,第一个答案应该2不是1。至于第二个答案,最好是一个空的子字符串返回0作为连接。

以下代码将处理这些事情。

def num_of_patterns(astr,pattern):
    astr, pattern = astr.strip(), pattern.strip()
    if pattern == '': return 0

    ind, count, start_flag = 0,0,0
    while True:
        try:
            if start_flag == 0:
                ind = astr.index(pattern)
                start_flag = 1
            else:
                ind += 1 + astr[ind+1:].index(pattern)
            count += 1
        except:
            break
    return count

现在,当我们运行它时:

>>>num_of_patterns('caatatab', 'ata') #overlapping
2
>>>num_of_patterns('caatatab', '') #empty string
0
>>>num_of_patterns('abcdabcva','ab') #normal
2

6

方案1:句子中出现单词。例如:str1 = "This is an example and is easy"。单词“是”的出现。让我们str2 = "is"

count = str1.count(str2)

场景2:句子中出现模式。

string = "ABCDCDC"
substring = "CDC"

def count_substring(string,sub_string):
    len1 = len(string)
    len2 = len(sub_string)
    j =0
    counter = 0
    while(j < len1):
        if(string[j] == sub_string[0]):
            if(string[j:j+len2] == sub_string):
                counter += 1
        j += 1

    return counter

谢谢!


我们真的需要检查吗if(string [j] == sub_string [0]):吗?是否在随后的if条件中自动覆盖?
AnandViswanathan89

AnandViswanathan89,如果两个条件都需要,if(string [j] == sub_string [0])检查主字符串中的初始字符匹配,这必须对主字符串和if(string [ j:j + len2] == sub_string)执行子字符串的出现。如果是第一次发生,那么如果条件满足则第二次发生。
Amith VV

4

问题不是很清楚,但是我会从表面上回答您的问题。

长度为L个字符的字符串S,其中S [1]是字符串的第一个字符,S [L]是最后一个字符,具有以下子字符串:

  • 空字符串“”。其中之一。
  • 对于从1到L的每个值A,对于从A到L的每个值B,字符串S [A] .. S [B](含)。这些字符串中有L + L-1 + L-2 + ... 1个,总计为0.5 * L *(L + 1)。
  • 请注意,第二项包括S [1] .. S [L],即整个原始字符串S。

因此,在长度为L的字符串中有0.5 * L *(L + 1)+ 1个子字符串。在Python中渲染该表达式,您可以在字符串中找到子字符串的数量。


4

一种方法是使用re.subn。例如,要计算在多种情况下的出现次数,'hello'您可以执行以下操作:

import re
_, count = re.subn(r'hello', '', astring, flags=re.I)
print('Found', count, 'occurrences of "hello"')

为我说声,谢谢。@santosh,为什么不接受答案?
Mawg说恢复莫妮卡

2

我将保留我接受的答案作为“简单而明显的方法”-但是,这不包括重复出现的情况。找出这些结果可以天真地进行,只需对切片进行多次检查-如:sum(“ GCAAAAAGH” [i:]。startswith(“ AAA”)for range(len(“ GCAAAAAGH”)))

(产生3)-可以通过正则表达式的技巧性使用来完成,就像在Python regex中可以找到所有重叠的匹配项一样?-并且还可以使代码打高尔夫-这是我的“手工制作”计数字符串中模式重叠出现的原因,这种尝试不会太幼稚(至少在每次交互时它不会创建新的字符串对象):

def find_matches_overlapping(text, pattern):
    lpat = len(pattern) - 1
    matches = []
    text = array("u", text)
    pattern = array("u", pattern)
    indexes = {}
    for i in range(len(text) - lpat):
        if text[i] == pattern[0]:
            indexes[i] = -1
        for index, counter in list(indexes.items()):
            counter += 1
            if text[i] == pattern[counter]:
                if counter == lpat:
                    matches.append(index)
                    del indexes[index]
                else:
                    indexes[index] = counter
            else:
                del indexes[index]
    return matches

def count_matches(text, pattern):
    return len(find_matches_overlapping(text, pattern))

2

重叠事件:

def olpcount(string,pattern,case_sensitive=True):
    if case_sensitive != True:
        string  = string.lower()
        pattern = pattern.lower()
    l = len(pattern)
    ct = 0
    for c in range(0,len(string)):
        if string[c:c+l] == pattern:
            ct += 1
    return ct

test = 'my maaather lies over the oceaaan'
print test
print olpcount(test,'a')
print olpcount(test,'aa')
print olpcount(test,'aaa')

结果:

my maaather lies over the oceaaan
6
4
2

2

对于重叠计数,我们可以使用use:

def count_substring(string, sub_string):
    count=0
    beg=0
    while(string.find(sub_string,beg)!=-1) :
        count=count+1
        beg=string.find(sub_string,beg)
        beg=beg+1
    return count

对于不重叠的情况,我们可以使用count()函数:

string.count(sub_string)

2

列表理解的单线怎么样?从技术上讲,它的93个字符长,让我免于PEP-8的纯粹主义。如果regex.findall答案是一段高级代码,则它是最易读的。如果您正在构建低级的东西并且不想依赖,那么这是相当精简和卑鄙的。我给出了重叠的答案。显然,只要没有重叠,就可以像最高分数答案那样使用count。

def count_substring(string, sub_string):
    return len([i for i in range(len(string)) if string[i:i+len(sub_string)] == sub_string])

2

如果要计算所有子字符串(包括重叠的),请使用此方法。

import re
def count_substring(string, sub_string):
    regex = '(?='+sub_string+')'
    # print(regex)
    return len(re.findall(regex,string))

1

如果要查找任何字符串中的子字符串计数;请使用以下代码。该代码很容易理解,这就是我跳过注释的原因。:)

string=raw_input()
sub_string=raw_input()
start=0
answer=0
length=len(string)
index=string.find(sub_string,start,length)
while index<>-1:
    start=index+1
    answer=answer+1
    index=string.find(sub_string,start,length)
print answer

0

我不确定这是否已经被研究过,但我认为这是“一次性”一词的解决方案:

for i in xrange(len(word)):
if word[:len(term)] == term:
    count += 1
word = word[1:]

print count

是字,你正在寻找并长期为你正在寻找术语


0
string="abc"
mainstr="ncnabckjdjkabcxcxccccxcxcabc"
count=0
for i in range(0,len(mainstr)):
    k=0
    while(k<len(string)):
        if(string[k]==mainstr[i+k]):
            k+=1
        else:
            break   
    if(k==len(string)):
        count+=1;   
print(count)

2
也许您可以详细说明此解决方案与其他解决方案有何不同,是否可以解决一个特殊情况?
mpaskov

2
尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。
唐老鸭

0
import re
d = [m.start() for m in re.finditer(seaching, string)] 
print (d)

这将查找在字符串中找到子字符串的次数并显示索引。


import re d = [re.finditer(st3,st2)中m的m.start()]#查找在字符串中找到子字符串的次数并显示索引打印(d)
Bhaskar Reddi K

0
my_string = """Strings are amongst the most popular data types in Python. 
               We can create the strings by enclosing characters in quotes.
               Python treats single quotes the same as double quotes."""

Count = my_string.lower().strip("\n").split(" ").count("string")
Count = my_string.lower().strip("\n").split(" ").count("strings")
print("The number of occurance of word String is : " , Count)
print("The number of occurance of word Strings is : " , Count)

0

冒风险投票的风险,因为已有2个以上的人提供了此解决方案。我什至赞成其中之一。但是我的可能是新手最容易理解的。

def count_substring(string, sub_string):
    slen  = len(string)
    sslen = len(sub_string)
    range_s = slen - sslen + 1
    count = 0
    for i in range(range_s):
        if (string[i:i+sslen] == sub_string):
            count += 1
    return count

0

对于带有空格分隔的简单字符串,使用Dict会非常快,请参见下面的代码

def getStringCount(mnstr:str, sbstr:str='')->int:
    """ Assumes two inputs string giving the string and 
        substring to look for number of occurances 
        Returns the number of occurances of a given string
    """
    x = dict()
    x[sbstr] = 0
    sbstr = sbstr.strip()
    for st in mnstr.split(' '):
        if st not in [sbstr]:
            continue
        try:
            x[st]+=1
        except KeyError:
            x[st] = 1
    return x[sbstr]

s = 'foo bar foo test one two three foo bar'
getStringCount(s,'foo')


0

下面的逻辑适用于所有字符串和特殊字符

def cnt_substr(inp_str, sub_str):
    inp_join_str = ''.join(inp_str.split())
    sub_join_str = ''.join(sub_str.split())

    return inp_join_str.count(sub_join_str)

print(cnt_substr("the sky is   $blue and not greenthe sky is   $blue and not green", "the sky"))

0

这是Python 3中不区分大小写的解决方案:

s = 'foo bar foo'.upper()
sb = 'foo'.upper()
results = 0
sub_len = len(sb)
for i in range(len(s)):
    if s[i:i+sub_len] == sb:
        results += 1
print(results)

0
j = 0
    while i < len(string):
        sub_string_out = string[i:len(sub_string)+j]
        if sub_string == sub_string_out:
            count += 1
        i += 1
        j += 1
    return count

2
尽管所有答案都值得赞赏,但仅代码答案往往无法很好地说明该主题。请添加一些上下文。
creyD

0
#counting occurence of a substring in another string (overlapping/non overlapping)
s = input('enter the main string: ')# e.g. 'bobazcbobobegbobobgbobobhaklpbobawanbobobobob'
p=input('enter the substring: ')# e.g. 'bob'

counter=0
c=0

for i in range(len(s)-len(p)+1):
    for j in range(len(p)):
        if s[i+j]==p[j]:
            if c<len(p):
                c=c+1
                if c==len(p):
                    counter+=1
                    c=0
                    break
                continue
        else:
            break
print('number of occurences of the substring in the main string is: ',counter)

0
s = input('enter the main string: ')
p=input('enter the substring: ')
l=[]
for i in range(len(s)):
    l.append(s[i:i+len(p)])
print(l.count(p))

0

这将列出字符串中所有出现的事件(也重叠),并对它们进行计数

def num_occ(str1, str2):
    l1, l2 = len(str1), len(str2)
    return len([str1[i:i + l2] for i in range(l1 - l2 + 1) if str1[i:i + l2] == str2])

例:

str1 ='abcabcd'
str2 = 'bc'

将创建此列表,但仅保存BOLD值:

[ab,bc,ca,ab,bc,cd]

这将返回:

len([bc, bc])

1
请考虑加入至少部分解释,为什么虽然这个答案的问题
β.εηοιτ.βε

0

这是一个适用于非重叠和重叠事件的解决方案。需要说明的是:重叠的子字符串是最后一个字符与其第一个字符相同的子字符串。

def substr_count(st, sub):
    # If a non-overlapping substring then just
    # use the standard string `count` method
    # to count the substring occurences
    if sub[0] != sub[-1]:
        return st.count(sub)

    # Otherwise, create a copy of the source string,
    # and starting from the index of the first occurence
    # of the substring, adjust the source string to start
    # from subsequent occurences of the substring and keep
    # keep count of these occurences
    _st = st[::]
    start = _st.index(sub)
    cnt = 0

    while start is not None:
        cnt += 1
        try:
            _st = _st[start + len(sub) - 1:]
            start = _st.index(sub)
        except (ValueError, IndexError):
            return cnt

    return cnt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.