Đếm số lần xuất hiện của một chuỗi con đã cho trong một chuỗi


201

Làm cách nào tôi có thể đếm số lần một chuỗi con đã cho có trong một chuỗi trong Python?

Ví dụ:

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

"Số chuỗi con" nghĩa là gì? Vị trí của chuỗi con? Bao nhiêu lần chuỗi con xảy ra? Thứ gì khác?
GreenMatt

2
Đây có phải là một bài tập về nhà? Nếu vậy, vui lòng thêm thẻ "bài tập về nhà" vào câu hỏi của bạn. Ngoài ra, câu hỏi của bạn không rõ ràng lắm. Tôi sẽ trả lời những gì bạn dường như đang hỏi, nhưng tôi nghi ngờ bạn thực sự muốn tìm hiểu điều gì khác.
Jim DeLaHunt

Theo dõi nhận xét trước đó, bạn có thể muốn xem: python: Cách tìm chuỗi con trong chuỗi khác hoặc lặp lại lập chỉ mục cơ bản của chuỗi con trong chuỗi (python) . Vì đây có vẻ là một bản sao của một trong số đó, tôi sẽ bỏ phiếu để đóng.
GreenMatt

@JimDeLaHunt Đối với các hồ sơ, có một bài tập về điều này trong cscircles.cemc.uwaterloo.ca/8-remix - xem Bài tập mã hóa: Đếm chuỗi con .
Nikos Alexandris

Câu trả lời:


334

string.count(substring), giống như trong:

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

Cập nhật:

Như đã chỉ ra trong các ý kiến, đây là cách để làm điều đó cho các lần xuất hiện không chồng chéo . Nếu bạn cần tính các lần xuất hiện chồng chéo, tốt hơn bạn nên kiểm tra các câu trả lời tại: " Python regex tìm thấy tất cả các kết quả trùng lặp? ", Hoặc chỉ kiểm tra câu trả lời khác của tôi bên dưới.


14
Điều gì về điều này: "GCAAAAAG".count("AAA")cho 1, trong khi câu trả lời đúng là 3?
vẽ tranh biếm họa

12
countrõ ràng là cho các trận đấu không chồng chéo - thường là những gì người ta muốn làm. stackoverflow.com/questions/5616822/ Giao dịch với các trận đấu chồng chéo - nhưng một biểu thức đơn giản, nếu đắt tiền là:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno

Có thể đếm / tìm kiếm nhiều từ cùng một lúc không? như string.count (chuỗi con1, chuỗi con2)
Sushant Kulkarni

@SushantKulkarni Không. Mặc dù có một cách hợp lý để làm một việc như vậy : string.count(substring1) + string.count(substring2). Nhưng hãy nhớ rằng đây không phải là một phương pháp hiệu quả nếu có nhiều chuỗi con bởi vì đếm từng chuỗi con đòi hỏi phải lặp lại chuỗi chính.
Faheel

@SushantKulkarni làm ''.join([substring1, substring2]).count(pattern)hiệu quả hơn giải pháp được đề xuất ở trên. Tôi đã kiểm tra bằng timeit.
Enric Calabuig

23
s = 'arunununghhjj'
sb = 'nun'
results = 0
sub_len = len(sb)
for i in range(len(s)):
    if s[i:i+sub_len] == sb:
        results += 1
print results

4
Giải thích thêm sẽ cải thiện câu trả lời của bạn.
ryanyuyu

19

Tùy thuộc vào ý nghĩa thực sự của bạn, tôi đề xuất các giải pháp sau:

  1. Bạn có nghĩa là một danh sách các chuỗi con được phân tách bằng dấu cách và muốn biết số vị trí của chuỗi con là gì trong số tất cả các chuỗi con:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Bạn có nghĩa là vị trí char của chuỗi con trong chuỗi:

    s.find('sub2')
    >>> 5
  3. Bạn có nghĩa là số lần xuất hiện (không chồng lấp) của chuỗi su:

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

Cố gắng tìm 'phụ' hoặc 'su'
obohovyk

Tôi đoán bạn có ý nghĩa s.find("su")và tự hỏi tại sao bạn nhận được 0? Vâng, đây là chỉ mục đầu tiên của chuỗi con "su"trong s. Hãy thử "ub"và bạn sẽ nhận được 1, thử ví dụ "z"và bạn sẽ nhận được -1như không tìm thấy chuỗi con nào.
Don Câu hỏi

Ý tôi là bạn luôn chỉ tìm thấy chỉ mục đầu tiên, nhưng không phải tất cả các chỉ mục, @ arun-kumar-khattri đã đưa ra câu trả lời đúng
obohovyk

Tôi cảm thấy nhẹ nhõm vì @ arun-kumar-khattri đã đưa ra câu trả lời "đúng" mà bạn đang tìm kiếm. Có lẽ bạn nên xem xét thêm về ý kiến ​​của jsbueno, đôi khi họ trả lời những câu hỏi mà bạn chưa hỏi.
Don Câu hỏi

Giống như cho cách tiếp cận thứ ba. BTW, tôi nghĩ bạn nên đề cập rằng nó hoạt động cho các trường hợp không chồng chéo.
Zeinab Abbasimazar

12

Cách tốt nhất để tìm chuỗi phụ chồng chéo trong một chuỗi đã cho là sử dụng biểu thức chính quy python, nó sẽ tìm tất cả các kết hợp trùng lặp bằng thư viện biểu thức chính quy. Dưới đây là cách thực hiện bên trái là chuỗi con và bên phải bạn sẽ cung cấp chuỗi phù hợp

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

2
có lẽ bạn có thể thêm len (re.findall (f '(? = {sub_opes})', 'caaaab')) để chèn chuỗi phụ một cách linh hoạt :)
Amresh Giri

10

Để tìm sự xuất hiện chồng lấp của một chuỗi con trong một chuỗi trong Python 3, thuật toán này sẽ thực hiện:

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  

Bản thân tôi đã kiểm tra thuật toán này và nó đã hoạt động.


1
Mẹo nhỏ: Thay vì nói "Nó hoạt động vì tôi đã kiểm tra nó", bạn có thể bao gồm một ví dụ trên một dịch vụ trực tuyến như repl.it với một số dữ liệu mẫu.
Valentin ngày

1
cảm ơn bạn đã bình luận Valentin! Đây là câu trả lời đầu tiên của tôi ở đây. Tôi sẽ cải thiện bản thân từ câu trả lời tiếp theo của tôi.
Bharath Kumar R

10

Bạn có thể đếm tần số bằng hai cách:

  1. Sử dụng count()trong str:

    a.count(b)

  2. Hoặc, bạn có thể sử dụng:

    len(a.split(b))-1

Trong trường hợp alà chuỗi và blà chuỗi con có tần số là phải được tính toán.


7

Câu trả lời tốt nhất hiện nay liên quan đến phương pháp count không thực sự được tính cho các lần xuất hiện chồng chéo và cũng không quan tâm đến các chuỗi con trống. Ví dụ:

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

Câu trả lời đầu tiên nên 2không 1, nếu chúng ta xem xét các chuỗi con chồng chéo. Đối với câu trả lời thứ hai, sẽ tốt hơn nếu một chuỗi con trống trả về 0 dưới dạng asnwer.

Các mã sau đây chăm sóc những điều này.

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

Bây giờ khi chúng tôi chạy nó:

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

6

Kịch bản 1: Xuất hiện một từ trong câu. ví dụ : str1 = "This is an example and is easy". Sự xuất hiện của từ "là". hãystr2 = "is"

count = str1.count(str2)

Kịch bản 2: Xuất hiện mẫu trong câu.

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

Cảm ơn!


chúng ta có thực sự cần kiểm tra này không nếu (chuỗi [j] == sub_ chuỗi [0]) :? Nó không tự động được bảo hiểm trong điều kiện tiếp theo?
AnandViswanathan89

AnandViswanathan89, Cả hai nếu điều kiện là bắt buộc, if (chuỗi [j] == sub_opes [0]) kiểm tra khớp ký tự ban đầu trong chuỗi chính, phải được thực hiện cho toàn bộ các ký tự của chuỗi chính và if (chuỗi [ j: j + len2] == sub_ chuỗi) thực hiện sự xuất hiện của chuỗi con. Nếu nó là lần xuất hiện đầu tiên thì lần thứ hai nếu điều kiện sẽ có hiệu lực.
Amith VV

4

Câu hỏi không rõ ràng lắm, nhưng tôi sẽ trả lời bạn là gì, trên bề mặt, hỏi.

Một chuỗi S, dài L ký tự và trong đó S [1] là ký tự đầu tiên của chuỗi và S [L] là ký tự cuối cùng, có các chuỗi con sau:

  • Chuỗi null ''. Có một trong số này.
  • Với mọi giá trị A từ 1 đến L, với mọi giá trị B từ A đến L, chuỗi S [A] .. S [B] (đã bao gồm). Có L + L-1 + L-2 + ... 1 trong số các chuỗi này, với tổng số 0,5 * L * (L + 1).
  • Lưu ý rằng mục thứ hai bao gồm S [1] .. S [L], tức là toàn bộ chuỗi gốc S.

Vì vậy, có 0,5 * L * (L + 1) + 1 chuỗi con trong một chuỗi có độ dài L. Kết xuất biểu thức đó trong Python và bạn có số lượng chuỗi con có trong chuỗi.


4

Một cách là sử dụng re.subn. Ví dụ: để đếm số lần xuất hiện 'hello'trong bất kỳ trường hợp kết hợp nào bạn có thể làm:

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

Lời cho tôi, cảm ơn. @santosh, tại sao không chấp nhận một câu trả lời?
Mawg nói rằng phục hồi Monica

2

Tôi sẽ giữ câu trả lời được chấp nhận của mình là "cách đơn giản và rõ ràng để làm điều đó" - tuy nhiên, điều đó không bao gồm các sự cố chồng chéo. Việc tìm ra chúng có thể được thực hiện một cách ngây thơ, với nhiều lần kiểm tra các lát - như trong: sum ("GCAAAAAGH" [i:]. Startedwith ("AAA") cho i trong phạm vi (len ("GCAAAAAGH")))

(mang lại 3) - nó có thể được thực hiện bằng cách sử dụng thủ thuật biểu thức chính quy, như có thể thấy tại regex Python tìm thấy tất cả các kết quả trùng khớp? - và nó cũng có thể tạo ra việc chơi golf mã tốt - Đây là số lần "làm bằng tay" của tôi cho các mẫu chồng chéo trong một chuỗi cố gắng không quá ngây thơ (ít nhất là nó không tạo ra các đối tượng chuỗi mới trong mỗi tương tác):

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

Sự xuất hiện chồng chéo:

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

Các kết quả:

my maaather lies over the oceaaan
6
4
2

2

Để tính chồng chéo, chúng ta có thể sử dụng:

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

Đối với trường hợp không chồng lấp, chúng ta có thể sử dụng hàm Count ():

string.count(sub_string)

2

Làm thế nào về một lót với một sự hiểu biết danh sách? Về mặt kỹ thuật, nó dài 93 ký tự, dành cho tôi tính thuần túy PEP-8. Câu trả lời regex.findall là dễ đọc nhất nếu đó là một đoạn mã cấp cao. Nếu bạn đang xây dựng một cái gì đó ở mức độ thấp và không muốn phụ thuộc, thì cái này khá nạc và có ý nghĩa. Tôi đang đưa ra câu trả lời chồng chéo. Rõ ràng chỉ sử dụng số đếm như câu trả lời điểm cao nhất nếu không có sự trùng lặp.

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

Nếu bạn muốn đếm tất cả các chuỗi con (bao gồm cả chồng chéo) thì hãy sử dụng phương pháp này.

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

1

Nếu bạn muốn tìm ra số lượng chuỗi con bên trong bất kỳ chuỗi nào; vui lòng sử dụng mã dưới đây. Mã rất dễ hiểu đó là lý do tại sao tôi bỏ qua các bình luận. :)

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

Tôi không chắc đây có phải là thứ gì đó đã được xem hay không, nhưng tôi nghĩ đây là một giải pháp cho một từ 'dùng một lần':

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

print count

Trong trường hợp từ là từ mà bạn đang tìm kiếm tại và hạn là một thuật ngữ bạn đang tìm kiếm


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
Có lẽ bạn có thể giải thích làm thế nào giải pháp này khác với giải pháp khác, có một trường hợp đặc biệt mà nó có thể giải quyết?
mpaskov

2
Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Vịt Donald

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

Điều này tìm thấy số lần chuỗi phụ được tìm thấy trong chuỗi và hiển thị chỉ mục.


nhập re d = [m.start () cho m trong re.finditer (st3, st2)] #finding số lần chuỗi con được tìm thấy trong chuỗi và hiển thị chỉ mục in (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

Có nguy cơ downvote vì hơn 2 người khác đã cung cấp giải pháp này. Tôi thậm chí còn ủng hộ một trong số họ. Nhưng tôi có lẽ là người dễ hiểu nhất.

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

Đối với một chuỗi đơn giản với phân định không gian, sử dụng Dict sẽ khá nhanh, vui lòng xem mã như dưới đây

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

Bạn có thể sử dụng startswithphương pháp:

def count_substring(string, sub_string):
    x = 0
    for i in range(len(string)):
        if string[i:].startswith(sub_string):
            x += 1
    return x

0

Dưới đây logic sẽ hoạt động cho tất cả các chuỗi và ký tự đặc biệt

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

Đây là giải pháp trong Python 3 và trường hợp không nhạy cảm:

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
Trong khi tất cả các câu trả lời được đánh giá cao, mã chỉ có câu trả lời có xu hướng không giải thích chủ đề rất tốt. Vui lòng thêm một số bối cảnh.
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

Điều này tạo một danh sách tất cả các lần xuất hiện (cũng chồng chéo) trong chuỗi và đếm chúng

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

Thí dụ:

str1 ='abcabcd'
str2 = 'bc'

sẽ tạo danh sách này nhưng chỉ lưu các giá trị BÓNG :

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

điều đó sẽ trở lại:

len([bc, bc])

1
Vui lòng xem xét thêm ít nhất một số lời giải thích như thể tại sao điều này trả lời câu hỏi
.εη εηττ

0

Đây là một giải pháp hoạt động cho cả các sự cố không chồng chéo và chồng chéo. Để làm rõ: một chuỗi con chồng chéo là một chuỗi có ký tự cuối cùng giống với ký tự đầu tiên của nó.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.