Zählen Sie die Anzahl der Vorkommen eines bestimmten Teilstrings in einer Zeichenfolge


201

Wie kann ich zählen, wie oft eine bestimmte Teilzeichenfolge in einer Zeichenfolge in Python vorhanden ist?

Beispielsweise:

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

Was meinst du mit "Anzahl der Teilzeichenfolgen"? Die Position des Teilstrings? Wie oft kommt der Teilstring vor? Etwas anderes?
GreenMatt

2
Ist das eine Hausaufgabe? Wenn ja, fügen Sie Ihrer Frage bitte den Tag "Hausaufgaben" hinzu. Auch Ihre Frage ist nicht sehr klar. Ich werde antworten, was Sie zu fragen scheinen, aber ich vermute, Sie möchten wirklich etwas anderes herausfinden.
Jim DeLaHunt

Nach dem vorherigen Kommentar möchten Sie möglicherweise Folgendes sehen: Python: So finden Sie eine Teilzeichenfolge in einer anderen Zeichenfolge oder grundlegende Indizierungsrezidive einer Teilzeichenfolge in einer Zeichenfolge (Python) . Da dies wahrscheinlich ein Duplikat davon ist, stimme ich für den Abschluss.
GreenMatt

@JimDeLaHunt Für die Aufzeichnungen gibt es eine Übung dazu in cscircles.cemc.uwaterloo.ca/8-remix - siehe Codierungsübung: Teilstring-Zählung .
Nikos Alexandris

Antworten:


334

string.count(substring), wie in:

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

Aktualisieren:

Wie in den Kommentaren erwähnt, ist dies der Weg, um dies bei nicht überlappenden Ereignissen zu tun . Wenn Sie überlappende Vorkommen zählen müssen, überprüfen Sie die Antworten besser unter: " Python-Regex findet alle überlappenden Übereinstimmungen? " Oder überprüfen Sie einfach meine andere Antwort unten.


14
Was ist damit: Was "GCAAAAAG".count("AAA")gibt 1, während die richtige Antwort 3 ist?
Karikaturist

12
countist offensichtlich für nicht überlappende Spiele - was meistens das ist, was man tun möchte. stackoverflow.com/questions/5616822/… befasst sich mit überlappenden Übereinstimmungen - aber ein einfacher, wenn auch teurer Ausdruck lautet:sum("GCAAAAAGH"[i:].startswith("AAA") for i in range(len("GCAAAAAGH")))
jsbueno

Ist es möglich, mehrere Wörter gleichzeitig zu zählen / zu suchen? wie string.count (Teilzeichenfolge1, Teilzeichenfolge2)
Sushant Kulkarni

@SushantKulkarni Nein. Obwohl es einen logischen Weg gibt, so etwas zu tun : string.count(substring1) + string.count(substring2). Beachten Sie jedoch, dass dies keine effiziente Methode ist, wenn viele Teilzeichenfolgen vorhanden sind, da für das Zählen der einzelnen Teilzeichenfolgen eine Iteration über die Hauptzeichenfolge erforderlich ist.
Faheel

@SushantKulkarni ''.join([substring1, substring2]).count(pattern)ist effizienter als die oben vorgeschlagene Lösung. Ich habe mit timeit nachgesehen.
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
Eine zusätzliche Erklärung würde Ihre Antwort verbessern.
Ryanyuyu

19

Je nachdem, was Sie wirklich meinen, schlage ich folgende Lösungen vor:

  1. Sie meinen eine Liste von durch Leerzeichen getrennten Unterzeichenfolgen und möchten wissen, wie die Positionsnummer der Unterzeichenfolge unter allen Unterzeichenfolgen lautet:

    s = 'sub1 sub2 sub3'
    s.split().index('sub2')
    >>> 1
  2. Sie meinen die Zeichenposition der Unterzeichenfolge in der Zeichenfolge:

    s.find('sub2')
    >>> 5
  3. Sie meinen die (nicht überlappende) zählt der Auftritt eines su-bstring:

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

Versuchen Sie, 'sub' oder 'su' zu finden
obohovyk

Ich denke du meinst s.find("su")und fragst dich warum du bekommst 0? Nun, dies ist der erste Index der Unterzeichenfolge "su"in s. Versuchen Sie "ub"und Sie werden bekommen 1, versuchen Sie zB "z"und Sie werden -1wie in keinem Teilstring gefunden.
Don Frage

Ich meine, Sie finden immer nur den ersten Index, aber nicht alle Indizes. @ Arun-kumar-khattri gab die richtige Antwort
obohovyk

Ich bin erleichtert, dass @ arun-kumar-khattri die "richtige" Antwort gegeben hat, nach der Sie gesucht haben. Vielleicht sollten Sie sich die Kommentare von jsbueno genauer ansehen, manchmal beantworten sie Fragen, die Sie gerade noch nicht gestellt haben.
Don Frage

Wie beim dritten Ansatz. Übrigens, ich denke, Sie sollten erwähnen, dass es für nicht überlappende Fälle funktioniert.
Zeinab Abbasimazar

12

Der beste Weg, um überlappende Unterzeichenfolgen in einer bestimmten Zeichenfolge zu finden, besteht darin, den regulären Python-Ausdruck zu verwenden, der alle überlappenden Übereinstimmungen mithilfe der Bibliothek für reguläre Ausdrücke findet. Hier ist, wie es gemacht wird. Links ist der Teilstring und rechts geben Sie den passenden String an

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

2
Vielleicht könnten Sie len (re.findall (f '(? = {sub_string})', 'caaaab')) hinzufügen, um den
Substring

10

Um überlappende Vorkommen eines Teilstrings in einer Zeichenfolge in Python 3 zu finden, führt dieser Algorithmus Folgendes aus:

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  

Ich selbst habe diesen Algorithmus überprüft und er hat funktioniert.


1
Kleiner Tipp: Anstatt "Es funktioniert, weil ich es überprüft habe" zu sagen, können Sie ein Beispiel in einen Onlinedienst wie repl.it mit einigen Beispieldaten aufnehmen.
Valentin

1
Danke für deinen Kommentar Valentin! Es ist meine erste Antwort hier. Ich werde mich von meinen nächsten Antworten verbessern.
Bharath Kumar R

10

Sie können die Häufigkeit auf zwei Arten zählen:

  1. Verwenden des count()in str:

    a.count(b)

  2. Oder Sie können verwenden:

    len(a.split(b))-1

Wo aist der String und bist der Teilstring, dessen Häufigkeit berechnet werden soll.


7

Die derzeit beste Antwort mit der Methode countzählt nicht wirklich für überlappende Vorkommen und kümmert sich auch nicht um leere Teilzeichenfolgen. Beispielsweise:

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

Die erste Antwort sollte 2nicht sein 1, wenn wir die überlappenden Teilzeichenfolgen betrachten. Für die zweite Antwort ist es besser, wenn eine leere Unterzeichenfolge 0 als Antwort zurückgibt.

Der folgende Code kümmert sich um diese Dinge.

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

Jetzt, wenn wir es ausführen:

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

6

Szenario 1: Vorkommen eines Wortes in einem Satz. zB : str1 = "This is an example and is easy". Das Auftreten des Wortes "ist". Lasst unsstr2 = "is"

count = str1.count(str2)

Szenario 2: Auftreten eines Musters in einem Satz.

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

Vielen Dank!


Brauchen wir diese Prüfung wirklich, wenn (string [j] == sub_string [0]) :? Wird es nicht automatisch in der Folgezeit abgedeckt?
AnandViswanathan89

AnandViswanathan89, Beide, wenn Bedingungen erforderlich sind, wenn (string [j] == sub_string [0]) nach der anfänglichen Zeichenübereinstimmung innerhalb des Hauptstrings sucht, die für die gesamten Zeichen des Hauptstrings ausgeführt werden muss, und if (string [ j: j + len2] == sub_string) führt das Auftreten von Teilzeichenfolgen aus. Wenn es für das erste Auftreten ist, dann das zweite, wenn die Bedingung genügt hätte.
Amith VV

4

Die Frage ist nicht sehr klar, aber ich werde antworten, was Sie an der Oberfläche fragen.

Eine Zeichenfolge S, die L Zeichen lang ist und bei der S [1] das erste Zeichen der Zeichenfolge und S [L] das letzte Zeichen ist, hat die folgenden Teilzeichenfolgen:

  • Die Nullzeichenfolge ''. Es gibt eine davon.
  • Für jeden Wert A von 1 bis L, für jeden Wert B von A bis L die Zeichenfolge S [A] .. S [B] (einschließlich). Es gibt L + L-1 + L-2 + ... 1 dieser Zeichenfolgen für insgesamt 0,5 * L * (L + 1).
  • Beachten Sie, dass der zweite Punkt S [1] .. S [L] enthält, dh die gesamte ursprüngliche Zeichenfolge S.

Es gibt also 0,5 * L * (L + 1) + 1 Teilzeichenfolgen in einer Zeichenfolge der Länge L. Rendern Sie diesen Ausdruck in Python, und Sie haben die Anzahl der Teilzeichenfolgen in der Zeichenfolge.


4

Eine Möglichkeit ist zu verwenden re.subn. Um beispielsweise die Anzahl der Vorkommen 'hello'in einer beliebigen Mischung von Fällen zu zählen, können Sie Folgendes tun:

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

Wort für mich, danke. @ Santosh, warum nicht eine Antwort akzeptieren?
Mawg sagt, Monica

2

Ich werde meine akzeptierte Antwort als "einfache und offensichtliche Möglichkeit" beibehalten - dies gilt jedoch nicht für überlappende Ereignisse. Das herauszufinden kann naiv erfolgen, indem die Slices mehrfach überprüft werden - wie in: sum ("GCAAAAAGH" [i:]. Startwith ("AAA") für i in range (len ("GCAAAAAGH")))

(was 3 ergibt) - kann dies durch Trick mit regulären Ausdrücken erfolgen, wie bei Python Regex zu sehen ist, finden Sie alle überlappenden Übereinstimmungen? - und es kann auch zu feinem Code-Golfen führen - Dies ist meine "handgemachte" Zählung für überlappende Musterwährungen in einer Zeichenfolge, die versucht, nicht extrem naiv zu sein (zumindest werden bei jeder Interaktion keine neuen Zeichenfolgenobjekte erstellt):

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

Überlappende Vorkommen:

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

Ergebnisse:

my maaather lies over the oceaaan
6
4
2

2

Für überlappende Zählungen können wir verwenden:

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

Für nicht überlappende Fälle können wir die Funktion count () verwenden:

string.count(sub_string)

2

Wie wäre es mit einem Einzeiler mit Listenverständnis? Technisch gesehen sind die 93 Zeichen lang und ersparen mir PEP-8-Purismus. Die Antwort regex.findall ist am besten lesbar, wenn es sich um einen Code auf hoher Ebene handelt. Wenn Sie etwas Niedriges bauen und keine Abhängigkeiten wollen, ist dieses ziemlich schlank und gemein. Ich gebe die überlappende Antwort. Verwenden Sie natürlich nur count wie die Antwort mit der höchsten Punktzahl, wenn es keine Überlappung gibt.

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

Wenn Sie alle Teilzeichenfolgen (einschließlich überlappender Zeichenfolgen) zählen möchten, verwenden Sie diese Methode.

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

1

Wenn Sie die Anzahl der Teilzeichenfolgen in einer Zeichenfolge ermitteln möchten; Bitte verwenden Sie den folgenden Code. Der Code ist leicht zu verstehen, deshalb habe ich die Kommentare übersprungen. :) :)

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

Ich bin mir nicht sicher, ob dies bereits angeschaut wurde, aber ich dachte, dies sei eine Lösung für ein Wort, das "verfügbar" ist:

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

print count

Wo Wort das Wort ist, nach dem Sie suchen, und Begriff der Begriff ist, nach dem Sie suchen


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
Vielleicht können Sie näher erläutern, wie sich diese Lösung von der anderen unterscheidet. Gibt es einen Sonderfall, den sie lösen kann?
mpaskov

2
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Donald Duck

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

Hiermit wird ermittelt, wie oft eine Unterzeichenfolge in der Zeichenfolge gefunden wurde, und der Index wird angezeigt.


import re d = [m.start () für m in re.finditer (st3, st2)] # Ermitteln der Häufigkeit, mit der die Unterzeichenfolge in der Zeichenfolge gefunden wurde, und Anzeigen des Indexdrucks (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

Ein Downvote riskieren, weil 2+ andere diese Lösung bereits bereitgestellt haben. Ich habe sogar einen von ihnen positiv bewertet. Aber meine ist wahrscheinlich für Neulinge am einfachsten zu verstehen.

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

Für eine einfache Zeichenfolge mit Leerzeichenbegrenzung wäre die Verwendung von Dict recht schnell. Weitere Informationen finden Sie im folgenden Code

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

Sie könnten die startswithMethode verwenden:

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

Die folgende Logik funktioniert für alle Zeichenfolgen und Sonderzeichen

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

Hier ist die Lösung in Python 3, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird:

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
Während alle Antworten geschätzt werden, erklären Antworten nur mit Code das Thema in der Regel nicht sehr gut. Bitte fügen Sie einen Kontext hinzu.
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

Dadurch wird eine Liste aller Vorkommen (auch überlappend) in der Zeichenfolge erstellt und gezählt

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

Beispiel:

str1 ='abcabcd'
str2 = 'bc'

erstellt diese Liste, speichert jedoch nur die BOLD- Werte:

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

das wird zurückkehren:

len([bc, bc])

1
Bitte erwägen Sie, zumindest eine Erklärung hinzuzufügen, als ob dies die Frage beantworten würde
β.εηοιτ.βε

0

Hier ist eine Lösung, die sowohl für nicht überlappende als auch für überlappende Vorkommen funktioniert. Zur Verdeutlichung: Ein überlappender Teilstring ist einer, dessen letztes Zeichen mit seinem ersten Zeichen identisch ist.

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.