2012-04-10 16 views
3

Ich habe die folgende Zeichenfolge:Konvertieren eine Zeichenfolge eine römische Zahl enthält, entspricht integer

str = "MMX Lions Television Inc" 

Und ich brauche es in konvertieren:

conv_str = "2010 Lions Television Inc" 

Ich habe die folgende Funktion eine römische umwandeln Ziffer in seine ganzen Zahl äquivalent:

numeral_map = zip(
    (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1), 
    ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I') 
) 

def roman_to_int(n): 
    n = unicode(n).upper() 

    i = result = 0 
    for integer, numeral in numeral_map: 
     while n[i:i + len(numeral)] == numeral: 
      result += integer 
      i += len(numeral) 
    return result 

Wie würde ich verwenden re.sub das zu tun die richtige Zeichenfolge hier bekommen?

(Anmerkung: Ich habe versucht, die regex hier beschriebenen. How do you match only valid roman numerals with a regular expression? aber es funktioniert nicht)

+1

Gibt es einen Grund Sie nicht einen straight-up-Wörterbuch mit für Ihre römischen Ziffern zu halten, und dann mit den Tasten den Wert zu erhalten? – Makoto

+2

@Makoto: Ja, weil die Reihenfolge, in der die Zahlen extrahiert werden, relevant ist. '1000' muss' M' sein - es kann nicht 'DD' oder' CCCCCCCCCC' sein, das Sie bekommen würden, wenn Sie ein Wörterbuch benutzen würden. Zumindest für Umrechnungen von dezimalen in römische Ziffern benötigen Sie die feste Reihenfolge der Ziffern. –

Antwort

2

re.sub() eine Funktion als Ersatz akzeptieren kann, wird die Funktion ein einziges Argument erhalten, die das Match-Objekt ist, und sollte eine Ersatzzeichenfolge zurückgeben. Sie haben bereits eine Funktion, um eine römische Ziffer in ein int zu konvertieren, damit dies nicht schwierig ist.

In Ihrem Fall, dass Sie eine Funktion wie diese wollen würde:

def roman_to_int_repl(match): 
    return str(roman_to_int(match.group(0))) 

Jetzt können Sie die regex von der Frage ändern Sie so verbunden, dass es Übereinstimmungen innerhalb einer größeren Zeichenfolge finden:

s = "MMX Lions Television Inc" 
regex = re.compile(r'\b(?=[MDCLXVI]+\b)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b') 
print regex.sub(roman_to_int_repl, s) 
Hier

ist eine Version der Regex, die in einer Zeichenfolge nicht ersetzen "LLC" würde:

regex = re.compile(r'\b(?!LLC)(?=[MDCLXVI]+\b)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b') 

Y ou könnte auch die ursprüngliche regex mit einer modifizierten Ersatzfunktion verwenden:

def roman_to_int_repl(match): 
    exclude = set(["LLC"]) # add any other strings you don't want to replace 
    if match.group(0) in exclude: 
     return match.group(0) 
    return str(roman_to_int(match.group(0))) 
+0

Danke, das funktioniert super. Wie würden Sie auch das "Re" dazu bringen, "LLC" zu ignorieren? – David542

+0

Zu Beginn der Regex, fügen Sie die folgende '(?! LLC \ b)', wenn eine größere Liste, die Sie nicht zulassen möchten, können Sie etwas wie folgt verwenden: '(?! (LLC | XXX | I) \ b) ' –

5

immer die Python Package Index versuchen, wenn für eine gemeinsame Funktion/Bibliothek suchen.

Dies ist die list of modules related to the keyword 'roman'.

Zum Beispiel ‚romanclass‘ eine Klasse hat, die die Umwandlung zu implementieren, unter Angabe der Dokumentation:

So a programmer can say: 

>>> import romanclass as roman 

>>> two = roman.Roman(2) 

>>> five = roman.Roman('V') 

>>> print (two+five) 

and the computer will print: 

VII 
+0

Danke, und wie würde dies auf das obige Problem angewendet werden? – David542

+0

Bei einer Schätzung: Extrahiere die römische Zahl aus der Zeichenkette mit Regex (wie bei der anderen Antwort, die du im OP verlinkt hast), dann benutze dieses Modul, um deine römische Zahl in eine Zahl umzuwandeln. Verwenden Sie Regex für das, was es gut ist (Strings finden) und dieses römische Modul für das, was es gut ist (Konvertieren von Zeichenfolgen in Zahlen) und Sie werden eine robuste Lösung haben. –

Verwandte Themen