Zunächst ist dies Hausaufgaben. (Ich konnte keinen Titel im Titel verwenden und nichts tauchte in der Tagliste unten für Hausaufgaben auf, also lass mich bitte wissen, ob ich etwas anderes in dieser Angelegenheit BEARBEITEN sollte).Python Regex passende Wörter mit sich wiederholenden Konsonanten
Also habe ich durch die Python-Dokumente gelesen und SO aufgefangen, mehrere Lösungen gefunden, die nahe an dem sind, was ich will, aber nicht genau.
Ich habe ein Wörterbuch, das ich in einen String lesen:
a
aa
aabbaa
...
z
Wir auf diesen Daten verschiedene Regex prasselt üben. Das spezifische Problem hier ist, eine Liste der Wörter zurückzugeben, die dem Muster entsprechen, NICHT Tupel mit den Gruppen innerhalb jedes Matches.
Zum Beispiel:
eine Teilmenge dieses Wörterbuch Gegeben wie:
someword
sommmmmeword
someworddddd
sooooomeword
Ich möchte zurück:
['sommmmmword', 'someworddddd']
NICHT:
[('sommmmword', 'mmmmm', ...), ...] # or any other variant
EDIT:
Meine Argumentation hinter dem obigen Beispiel ist, dass ich sehen möchte, wie ich vermeiden kann, einen zweiten Durchlauf über die Ergebnisse zu machen. Das heißt, anstatt zu sagen:
res = re.match(re.compile(r'pattern'), dictionary)
return [r[0] for r in res]
ich speziell einen Mechanismus will, wo ich gerade verwenden kann:
return re.match(re.compile(r'pattern'), dictionary)
Ich weiß, dass dumm klingen, aber ich tue dies, um wirklich in regex zu graben. Ich erwähne das unten.
Dies ist, was ich versucht habe:
# learned about back refs
r'\b([b-z&&[^eiou]])\1+\b' -> # nothing
# back refs were weird, I want to match something N times
r'\b[b-z&&[^eiou]]{2}\b' -> # nothing
Irgendwo in Test ich ein Muster bemerkt Dinge wie '\nsomeword'
zurück. Ich konnte nicht herausfinden, was es war, aber wenn ich das Muster wieder finde, werde ich es hier der Vollständigkeit halber hinzufügen.
# Maybe the \b word markers don't work how I think?
r'.*[b-z&&[^eiou]]{2}' -> # still nothing
# Okay lets just try to match something in between anything
r'.*[b-z&&[^eiou]].*' -> # nope
# Since its words, maybe I should be more explicit.
r'[a-z]*[b-z&&[^eiou]][a-z]*' -> # still nope
# Decided to go back to grouping.
r'([b-z&&[^eiou]])(\1)' # I realize set difference may be the issue
# I saw someone (on SO) use set difference claiming it works
# but I gave up on it...
# OKAY getting close
r'(([b-df-hj-np-tv-xz])(\2))' -> [('ll', 'l', 'l'), ...]
# Trying the the previous ones without set difference
r'\b(.*(?:[b-df-hj-np-tv-xz]{3}).*)\b' -> # returned everything (all words)
# Here I realize I need a non-greedy leading pattern (.* -> .*?)
r'\b(.*?(?:[b-df-hj-np-tv-xz]{3}).*)\b' -> # still everything
# Maybe I need the comma in {3,} to get anything 3 or more
r'\b(.*?(?:[b-df-hj-np-tv-xz]{3,}).*)\b' -> # still everything
# okay I'll try a 1 line test just in case
r'\b(.*?([b-df-hj-np-tv-xz])(\2{3,}).*)\b'
# Using 'asdfdffff' -> [('asdfdffff', 'f', 'fff')]
# Using dictionary -> [] # WAIT WHAT?!
Wie funktioniert das letzte? Vielleicht gibt es keine 3+ wiederholten konsonanten Wörter? Ich benutze /usr/share/dict/cracklib-small
auf meinem Schulserver, der ungefähr 50.000 Wörter ist, denke ich.
Ich arbeite immer noch daran, aber jeder Rat wäre toll.
Eine Sache, die ich seltsam finde, ist, dass Sie nicht auf eine nicht einfangende Gruppe verweisen können. Wenn ich nur das vollständige Wort ausgeben möchte, verwende ich (?: ...), um eine Erfassung zu vermeiden, aber dann kann ich keine Referenz zurückgeben. Natürlich konnte ich die Captures verlassen, die Ergebnisse überfliegen und die zusätzlichen Sachen herausfiltern, aber ich möchte das unbedingt mit NUR Regex herausfinden!
Vielleicht gibt es eine Möglichkeit, das Nicht-Capture zu tun, aber immer noch zurück Referenz? Oder vielleicht gibt es einen ganz anderen Ausdruck, den ich noch nicht getestet habe.
Hausaufgaben in Ordnung ist hier zu fragen, wenn Sie Anstrengungen wettgemacht haben :) Können Sie bitte die Logik hinter "['sommmmmmword', 'someworddddd']' und nicht '[('sommmmword', 'mmmmm', ...), ...] teilen 'Auf welcher Grundlage diese beiden unterschieden werden ? –
Ah ja, tut mir leid, wenn das verwirrend schien. Ich habe einen Schnitt eingefügt. – spanishgum
1) Verwende 're.findall', um alle Ergebnisse zu erhalten, nicht' re.match' (das sucht nur nach 1 Übereinstimmung und nur beim String-Start). 2) '[b-z && [^ eiou]]' ist ein Java/ICU-Regex, diese Syntax wird von Python 're' nicht unterstützt. 3) Um "Extra" -Werte in Tupeln mit 're.findall' zu vermeiden, * verwenden Sie keine einfangenden Gruppen. Wenn Sie Rückverweise benötigen, verwenden Sie 're.finditer' anstelle von' re.findall' und greifen Sie auf '.group()' jeder Übereinstimmung zu. –