Python: wie zu bestimmen, ob eine Liste von Wörtern in einem string vorhanden ist
Gegeben eine Liste ["one", "two", "three"]
, wie um zu bestimmen, ob jedes Wort gibt es in einer angegebenen Zeichenfolge?
Den word-Liste ist ziemlich kurz (in meinem Fall weniger als 20 Wörter), aber die strings gesucht werden, ist ziemlich groß (über 400.000 strings für jeden Lauf)
Meine aktuelle Implementierung verwendet re
zu schauen, Spiele aber ich bin mir nicht sicher, ob es der beste Weg.
import re
word_list = ["one", "two", "three"]
regex_string = "(?<=\W)(%s)(?=\W)" % "|".join(word_list)
finder = re.compile(regex_string)
string_to_be_searched = "one two three"
results = finder.findall(" %s " % string_to_be_searched)
result_set = set(results)
for word in word_list:
if word in result_set:
print("%s in string" % word)
Probleme in meine Lösung:
- Wird es suchen, bis das Ende der Zeichenfolge, obwohl die Worte erscheinen in der ersten Hälfte der string
- Um zu überwinden die Beschränkung von lookahead-assertion (I don ' T know how to express "die Zeichen vor dem aktuellen Spiel sollten nicht-Wort-Zeichen, oder den Beginn der Zeichenfolge"), habe ich noch zusätzlichen Platz vor und nach der Zeichenfolge, die ich brauche, um gesucht werden.
- Andere performance-Problem, eingeführt durch die lookahead-assertion?
Möglich, eine einfachere Umsetzung:
- nur mit einer Schleife durch das Wort Liste und machen Sie einen
if word in string_to_be_searched
. Aber es kann nicht mit "Flotten Dreier", wenn Sie sind auf der Suche nach "drei" - Verwenden Sie eine Suche nach regulären Ausdrücken für ein Wort. Noch bin ich nicht sicher über die Leistung und das Potenzial der Suche Zeichenfolge mehrere Male.
UPDATE:
Habe ich akzeptiert, Aaron Hall, die Antwort https://stackoverflow.com/a/21718896/683321 denn laut Peter Gibson ' s benchmark https://stackoverflow.com/a/21742190/683321 diese einfache version hat die beste Leistung. Wenn Sie daran interessiert sind dieses problem, Lesen Sie alle Antworten und einen besseren überblick bekommen.
Eigentlich habe ich vergessen zu erwähnen, die ein weiteres Hindernis in meinem ursprünglichen problem. Das Wort ist ein Satz, zum Beispiel: word_list = ["one day", "second day"]
. Vielleicht sollte ich eine andere Frage stellen.
- warum nicht einfach aufteilen, das Wort in der string_to_be_searched und legte Sie in den dict und wiederholen Wörter in der such-Liste zu bestimmen
- dieses würde groß sein, wenn Sie hatte zu suchen, dass string_to_be_searched eine Menge, sondern der Aufbau eines Wörterbuchs in eine O(1) lookup einmal ist das nicht erstaunlich....
- Ich glaube, dass mein regulärer Ausdruck Lösung (stackoverflow.com/questions/21718345/...) funktionieren würde für Ihre weitere Einschränkung: es ist 4-mal langsamer, auch wenn es die 2. Schnellste, aber die Schnellste Lösung würde nicht funktionieren für, die. Es ist wahrscheinlich nicht eine gute Idee, Sie zu recyceln Ihre Frage mit einer zusätzlichen Einschränkung, aber ich könnte falsch sein es.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Funktion wurde von Peter Gibson (unten) werden die meisten performant von den Antworten hier. Es ist gut für die Datensätze kann man halt im Gedächtnis (weil es erstellt eine Liste der Wörter aus dem string gesucht werden und dann ein Satz, der diese Worte):
Verwendung:
Dem Drucke
One or words found!
auf stdout.Es hat zurück die tatsächlichen Worte gefunden:
Druckt:
Für Daten, die so groß, Sie können nicht halten Sie es im Speicher, die Lösung in dieser Antwort wäre sehr performant.
Zur Befriedigung meiner eigenen Neugier, habe ich zeitlich die Lösungen gepostet. Hier sind die Ergebnisse:
Interessanterweise @AaronHall Lösung
welche die Schnellste ist, ist auch eine der kürzesten! Beachten Sie es nicht handhaben Satzzeichen nächsten Worte, aber es ist nicht klar aus der Frage, ob das eine Voraussetzung. Diese Lösung wurde auch vorgeschlagen von @MIE und @user3.
Ich schaue nicht sehr lange an, warum sich zwei Lösungen haben nicht funktioniert. Entschuldigt, wenn dies ist mein Fehler. Hier ist der code für die tests, Kommentare & Korrekturen sind willkommen
string.split
mit einem der generator-version unter stackoverflow.com/questions/3862010/...Können Sie versuchen, diese:
Es wieder nur die übereinstimmenden Wörter aus Ihrer Wortliste. Wenn keine Worte abgestimmt, würde es wieder leere Liste.
Wenn Ihr string ist lang und Ihre Suche Liste kurz ist, dies zu tun:
for word in big_long_string
dies würde die Iteration über die Zeichen, nicht die richtigen Worte?split
kann sein, dass es erstellt eine neue Liste, in der Sie all die SaitenWenn die Reihenfolge nicht allzu wichtig, mithilfe dieses Ansatzes können Sie
Den
.split()
erstellt eine Liste, die kann ein problem für Ihre 400k Wort string. Aber wenn du genügend RAM hast, sind Sie fertig.Es ist natürlich möglich, ändern Sie die for-Schleife zu vermeiden, wird die gesamte Liste.
re.finditer
oder einen generator, der mitstr.find
sind die offensichtliche WahlNutzen Sie die Wortgrenzen:
EDIT: Wie in Ihrem Kommentar, Sie scheinen auf der Suche nach einem Wörterbuch statt:
str
wie ein Variablenname ist eine schlechte Idee.|
wie in der Fragebool
Wert, sondern ich bin auf der Suche nach einem dict-mappingword
zubool
. Außerdem kann ich Sie brauchen, um einige Tests und sehen Sie die performance von Laufendenre.search
mehrere Male, und führen Siere.findall
einmal.all
bedeutet, dass mehrere Iterationen geschieht außerhalb derre
ModulGegeben, Ihr Kommentar
Ich würde vorschlagen, die folgenden
Dieser gibt eine Liste von Wörtern gefunden, aber das könnten Sie leicht ändern, um wieder eine
dict{word:bool}
wie Sie es wünschen.Vorteile:
Einfach:
wenn Sie möchten, die Suche zu ignorieren Zeichen, die den Fall Sie dies tun können:
wenn Sie möchten, ignorieren Sie Wörter, die Teil eines größeren Worts wie in drei Dreier:
Wenn Leistung benötigt wird:
EDIT: diese Methode war der Schnellste in einem Beispiel, dass die Suche nach für 1.000 Wörter in einem string der über 400.000 Wörter, aber wenn wir erhöht die Zeichenfolge 4,000,000 der vorherigen Methode schneller ist.
wenn die Zeichenfolge ist zu lang, Sie sollten tun, low-level-such-und vermeiden konvertieren zu-Liste:
not_found
Liste enthält Wörter, die nicht gefunden werden, können Sie sich die Liste einfach, eine Möglichkeit istlist(set(search_list)-set(not_found))
EDIT: die Letzte Methode erscheint die langsamste.
Hier ist ein einfacher generator, der besser wäre für große Zeichenfolgen oder eine Datei, wie ich es anpassen in dem Abschnitt weiter unten.
Beachten Sie, dass dies sollte sehr schnell sein, aber es wird auch weiterhin so lange, wie der string weiter, ohne auf alle die Worte. Dies kam in der zweiten auf Peter Gibson benchmarking: Python: wie zu bestimmen, ob eine Liste von Wörtern in einem string vorhanden ist
Für eine schnellere Lösung für kürzere strings, siehe meine andere Antwort hier: Python: wie zu bestimmen, ob eine Liste von Wörtern in einem string vorhanden ist
Ursprüngliche Antwort
Geht es durch die string, woraus sich die Worte, wie er Sie findet, Verzicht auf die Suche nach ihm findet alle Wörter, oder wenn es erreicht, das Ende der Zeichenfolge.
Verwendung:
EDIT: die Anpassung zu verwenden, mit einer großen Datei:
Danke an Peter Gibson für die Suche nach dieser die zweite Schnellste Ansatz. Ich bin ziemlich stolz auf die Lösung. Da der beste Anwendungsfall ist eine riesige text-stream, lassen Sie mich anzupassen, die oben beschriebene Funktion mit einer Datei. Bitte beachten Sie, dass, wenn die Worte sind gebrochen auf diese Zeilenumbrüche nicht fangen, aber weder würden die anderen Methoden hier.
Zu demonstrieren, schreiben wir einige Daten:
und Verwendung:
wir haben jetzt einen iterator, und wenn wir Sie konsumieren, mit einer Liste:
gibt es:
re.escape
aufword_list
vor der Verwendungre
? Kann man finden, für diese Worte mit regexp Metazeichen, nicht zu entsprechen, als gedacht.