586 Stimmen

Wie findet man alle Vorkommen einer Teilzeichenkette?

Python hat string.find() y string.rfind() um den Index einer Teilzeichenkette in einer Zeichenkette zu ermitteln.

Ich frage mich, ob es so etwas gibt wie string.find_all() die alle gefundenen Indizes zurückgeben kann (nicht nur den ersten vom Anfang oder den ersten vom Ende).

Zum Beispiel:

string = "test test test test"

print string.find('test') # 0
print string.rfind('test') # 15

#this is the goal
print string.find_all('test') # [0,5,10,15]

20 Stimmen

Was sollte 'ttt'.find_all('tt') zurückkehren?

4 Stimmen

Sollte er '0' zurückgeben. Natürlich muss es in einer perfekten Welt auch eine 'ttt'.rfind_all('tt') was '1' ergeben sollte.

5 Stimmen

Reine Anfragen zum Schreiben von Code sind auf Stack Overflow tabu - wir erwarten, dass sich die Fragen hier auf spezifisch Programmierprobleme - aber wir helfen Ihnen gerne, sie selbst zu schreiben! Sagen Sie es uns was Sie ausprobiert haben und wo Sie feststecken. Dies wird uns auch helfen, Ihre Frage besser zu beantworten.

786voto

moinudin Punkte 125641

Es gibt keine einfache eingebaute String-Funktion, die das tut, wonach Sie suchen, aber Sie können die mächtigere reguläre Ausdrücke :

import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]

Wenn Sie sich überschneidende Übereinstimmungen finden wollen, Vorausschauende Betrachtung wird das tun:

[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]

Wenn Sie eine umgekehrte Suche ohne Überschneidungen wünschen, können Sie positive und negative Vorausschau in einem Ausdruck wie diesem kombinieren:

search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]

re.finditer gibt eine ジェネレータ so könnten Sie die [] in den oben genannten zu () um einen Generator statt einer Liste zu erhalten, was effizienter ist, wenn man die Ergebnisse nur einmal durchläuft.

178voto

Karl Knechtel Punkte 55450
>>> help(str.find)
Help on method_descriptor:

find(...)
    S.find(sub [,start [,end]]) -> int

Wir können sie also selbst bauen:

def find_all(a_str, sub):
    start = 0
    while True:
        start = a_str.find(sub, start)
        if start == -1: return
        yield start
        start += len(sub) # use start += 1 to find overlapping matches

list(find_all('spam spam spam spam', 'spam')) # [0, 5, 10, 15]

Keine temporären Zeichenfolgen oder Regexe erforderlich.

87voto

thkala Punkte 80165

Hier ist ein (sehr ineffizienter) Weg, um die todos (d.h. auch überlappende) Übereinstimmungen:

>>> string = "test test test test"
>>> [i for i in range(len(string)) if string.startswith('test', i)]
[0, 5, 10, 15]

76voto

Idos Punkte 14727

Utilisez re.finditer :

import re
sentence = input("Give me a sentence ")
word = input("What word would you like to find ")
for match in re.finditer(word, sentence):
    print (match.start(), match.end())

Für word = "this" y sentence = "this is a sentence this this" ergibt dies die Ausgabe:

(0, 4)
(19, 23)
(24, 28)

68voto

AkiRoss Punkte 10706

Nochmals, alter Thread, aber hier ist meine Lösung mit einer ジェネレータ und einfach str.find .

def findall(p, s):
    '''Yields all the positions of
    the pattern p in the string s.'''
    i = s.find(p)
    while i != -1:
        yield i
        i = s.find(p, i+1)

Ejemplo

x = 'banananassantana'
[(i, x[i:i+2]) for i in findall('na', x)]

gibt zurück.

[(2, 'na'), (4, 'na'), (6, 'na'), (14, 'na')]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X