python: Zahlenbereich, um die übereinstimmende Zeichenfolge neu zu bestimmen

8

Dies könnte ein Problem sein, das bereits gelöst wurde, aber ich kann es nicht herausfinden. Ich habe zwei große Ganzzahlen, nennen wir sie start_number und end_number (sie stellen einen zusammenhängenden Block von Telefonnummern dar). Andere Zahlen (dargestellt als Strings) werden in mein System eingegeben, und ich muss Regex verwenden, um dies mit dem 'Bereich Regex' zu vergleichen, um zu sehen, ob der Zahlenstring entweder auf oder zwischen start_number und end_number liegt.

Zum Beispiel:

  • start_number = 99519000
  • end_number = 99519099

daher

  • expression = "^995190[0-9][0-9]$"

, damit ich schließlich die folgenden Beispielnummern zuordnen kann (die nacheinander bei meinem System ankommen und zu jeder Zeit ankommen können):

  • "99519000" & lt; - MATCH
  • "99519055" & lt; - MATCH
  • "99519099" & lt; - MATCH
  • "99519100" & lt; - NICHT PASSEND
  • "99512210" & lt; - NICHT PASSEND
  • "41234123" & lt; - NICHT PASSEND

Wie kann ich Python verwenden, um das Regex-Zeichenfolgenmuster " expression " zu erstellen, vorausgesetzt, dass ein sinnvolles start_number und end_number ? Ich habe mehrere Start- / Endnummernblöcke, für die ich Regex-Muster erstellen muss. Ich brauche nur einen Weg, diese Muster programmatisch zu erstellen.

Es ist fair anzunehmen:

  • Start_number ist immer kleiner als end_number
  • Immer wird eine positive ganze Zahl sein.
  • In meinem Fall werden start_number und end_number immer die gleiche 'Länge' haben (dh immer die gleiche Anzahl von 10 Zeichen haben, wenn es als String dargestellt wird), wenn es das Leben einfacher macht .

Bearbeiten: zur besseren Übersicht

    
TC Fox 24.07.2013, 09:18
quelle

1 Antwort

14

[vorausgesetzt, du brauchst das, weil es ein seltsames System eines Drittanbieters ist, das Regexp benötigt]

Neuer Ansatz

Je mehr ich über Frederiks Kommentar nachdenke, desto mehr stimme ich zu. Die Regexp-Engine sollte in der Lage sein, dies zu einem kompakten DFA zu kompilieren, selbst wenn die Eingabezeichenfolge lang ist. In vielen Fällen ist das Folgende eine sinnvolle Lösung:

%Vor%

(es funktioniert gut mit allen numerischen Bereichen in den folgenden Tests, einschließlich 99519000 - 99519099. Eine grobe Umschlag-Berechnung legt nahe, dass 9-stellige Zahlen mit 1 GB Speicher ungefähr das Limit sind. Das sind die meisten Zahlen diese Größe wird angepasst, wenn nur einige übereinstimmen, können Sie viel größer gehen.).

Alter Ansatz

[erneut aktualisiert, um noch kürzere Ergebnisse zu erzielen - abgesehen von der gelegentlichen \d\d ist es ungefähr so ​​gut wie von Hand generiert]

unter der Annahme, dass alle Zahlen die gleiche Länge haben (dh, wenn Sie auf der linken Seite einen Nullpunkt haben, falls nötig), funktioniert das:

%Vor%

Die Funktion regexp(lo, hi) erstellt eine Regexp, die Werte zwischen lo und hi (Null bis zur maximalen Länge aufgefüllt) entspricht. Sie müssen wahrscheinlich eine ^ vor und eine $ nach (wie im Testcode) setzen, um die Übereinstimmung als ganze Zeichenfolge zu erzwingen.

Der Algorithmus ist eigentlich ziemlich einfach - er teilt die Dinge rekursiv in gemeinsame Präfixe und "vollständige Blöcke" ein. Ein vollständiger Block ist etwa 200-599 und kann zuverlässig zugeordnet werden (in diesem Fall mit [2-5]\d{2} ).

123-599 wird in 123-199 und 200-599 aufgeteilt. Die letzte Hälfte ist ein vollständiger Block, die erste Hälfte hat ein gemeinsames Präfix von 1 und 23-99, das rekursiv als 23-29 (gemeinsames Präfix) und 30-99 (vollständiger Block) behandelt wird (und wir enden schließlich, weil Argumente zu jedem Anruf sind kürzer als die ursprüngliche Eingabe).

das einzige unangenehme Detail ist die prefix , die benötigt wird, weil die Argumente für regexp() ganze Zahlen sind, also wenn sie zum Generieren, sagen wir, die Regexp für 00-09 aufgerufen wird, erzeugt sie tatsächlich die Regexp für 0-9. ohne die führende 0.

Die Ausgabe besteht aus einer Reihe von Testfällen, in denen der Bereich und der Regexp angezeigt werden:

%Vor%

Es dauert eine Weile, bis der letzte Test über 99999999-Nummern läuft.

Die Ausdrücke sollten kompakt genug sein, um Puffergrenzen zu vermeiden (ich würde annehmen, dass die Speichergröße im ungünstigsten Fall proportional zum Quadrat der Anzahl der Stellen in der größten Zahl ist).

ps ich benutze Python 3, aber ich denke nicht, dass es hier einen großen Unterschied macht.

    
andrew cooke 24.07.2013, 16:51
quelle

Tags und Links