2016-04-30 13 views
0

Zuallererst, vollständige Offenlegung, arbeite ich an einer Hausaufgabe. Das Beispiel, das ich gebe, ist nicht das genaue Problem, aber wird mir helfen zu verstehen, was ich tun muss. Ich suche keine löffelweise Antwort, sondern um zu verstehen, was vor sich geht.Ruby Regex gsub! ohne zu verwenden, wenn

Ich versuche, eine Zeichenfolge zu nehmen wie:

"The Civil War started in 1861." 
"The American Revolution started in 1775." 

In diesem Beispiel würde Ich mag die gleiche Zeichenfolge zurück, aber mit dem entsprechenden Jahrhundert in Klammern nach

"The Civil War started in 1861. (Nineteenth Century)" 
"The American Revolution started in 1775. (Eighteenth Century)" 

Ich bin in der Lage zu gruppieren, was ich brauche mit der folgenden Regex

text.gsub!(/([\w ]*)(1861|1775).?/, '\1\2 (NOT SURE HERE)') 

Es wäre einfach mit Gruppierung zu sagen if \2 == 1861 anhängen geeignete Jahrhundert, aber die Spezifikationen sagen nein if Aussagen verwendet werden kann und ich bin sehr verloren. Auch der Wechsel, den ich in diesem Beispiel verwendet habe, funktioniert nur für die aufgeführten 2 Jahre und ich weiß, dass eine bessere Form der Bereichsanpassung verwendet werden müsste, um ganze Jahrhunderte im Gegensatz zu diesen 2 einzelnen Jahren zu erfassen.

Antwort

2

Zum einen - wie die Hardcoding der Jahre zu entfernen:

text.gsub!(/([\w ]*)([012]\d{3}).?/, '\1\2 (NOT SURE HERE)') 

Diese Dinge für die nächsten ~ 1k Jahren behandeln soll. Wenn Sie wissen, dass die Daten auf bestimmte Zeiträume beschränkt sind, können Sie genauer sein.


Für den anderen Teil - das Jahrhundert ist nur die ersten beiden Ziffern plus eins. Also teilen Sie das Jahr in zwei Teile auf und erhöhen Sie es.

text.gsub(/[\w ]*([012]\d)\d\d.?/) do |sentence| 
    "#{sentence} (#{$1.next}th Century)" 
end 

Beachten Sie die Verwendung von String#gsub with block aufgrund der Tatsache, dass wir eine Transformation auf eine der angepassten Gruppen durchführen müssen.


Update:, wenn Sie die Jahrhunderte in Worte sein möchten, können Sie ein Array verwenden, um sie zu speichern.

ordinals = %w(
    First Second Third Fourth Fifth Sixth Seventh Eighth Ninth Tenth Eleventh 
    Twelfth Thirteenth Fourteenth Fifteenth Sixteenth Seventeenth Eighteenth 
    Nineteenth Twentieth Twenty–First 
) 

text.gsub(/[\w ]*([012]\d)\d\d.?/) do |sentence| 
    "#{sentence} (#{ordinals[$1.to_i]} Century)" 
end 

Update (2): Angenommen, Sie etwas ganz anderes ersetzt werden soll, und Sie können nicht nutzen Anzahl Nettigkeiten wie im Jahrhunderte Beispiel nehmen, implementieren die gleiche allgemeine Idee, verwenden Sie einfach einen Hash statt Array:

replacements = {'cat' => 'king', 'mat' => 'throne'} 

"The cat sat on the mat.".gsub(/^(\w+)(\w+)([\w ]+)(\w+)\.$/) do 
    "#{$1}#{replacements[$2]}#{$3}#{replacements[$4]}." 
end 
+0

Das ist ein netter Weg, es mit den Jahrhunderten zu tun, aber vielleicht ein armes Beispiel meinerseits. Sagen wir, es muss das geschriebene Wort sein, wie "Neunzehntes Jahrhundert" statt 19.. Ich versuche mehr herauszufinden, wie ich etwas völlig anderes als den aufgenommenen Text ersetzen kann.Ich stelle nicht das genaue Problem geschrieben, weil ich nicht möchte, dass die Antwort um das Netz schwebt – kennedyl

+0

Die Blockform von 'gsub' reicht nur ein Argument zum Block, das volle Match. Um auf die Captures zugreifen zu können, müssen Sie '$ 1',' $ 2' usw. verwenden. –

+0

@Jordan, behoben Danke. – ndn

0

Angenommen, das Jahr ist zwischen 1 und 2099, könnten Sie es tun, wie folgt.

YEAR_TO_CENTURY = (1..21).to_a.zip(%w| First Second Third Fourth Fifth Sixth 
    Seventh Eighth Ninth Tenth Eleventh Twelfth Thriteenth Fourteenth Fifteenth 
    Sixteenth Seventeenth Eighteenth Nineteenth Twentieth Twentyfirst |).to_h 
    #=> { 1=>"First", 2=>"Second", 3=>"Third", 4=>"Fourth", 5=>"Fifth", 6=>"Sixth", 
    #  7=>"Seventh", 8=>"Eighth", 9=>"Ninth", 10=>"Tenth", 11=>"Eleventh", 
    # 12=>"Twelfth", 13=>"Thriteenth", 14=>"Fourteenth", 15=>"Fifteenth", 
    # 16=>"Sixteenth", 17=>"Seventeenth", 18=>"Eighteenth", 19=>"Nineteenth", 
    # 20=>"Twentieth", 21=>"Twentyfirst" } 

def centuryize(str) 
    str << " (%s Century)" % YEAR_TO_CENTURY[(str[/\d+(?=\.)/].to_i/100.0).ceil] 
end 

centuryize "The American Revolution started in 1775." 
    #=> "The American Revolution started in 1775. (Eighteenth Century)" 
centuryize "The Battle of Hastings took place in 1066." 
    #=> "The Battle of Hastings took place in 1066. (Eleventh Century)" 
centuryize "Nero played the fiddle while Rome burned in AD 64." 
    #=> "Nero played the fiddle while Rome burned in AD 64. (First Century)" 

Es wäre einfacher, wenn wir "19. Jahrhundert" schreiben könnten.

def centuryize(str) 
    century = (str[/\d+(?=\.)/].to_i/100.0).ceil 
    suffix = 
    case century 
    when 1, 21 then "st" 
    when 2  then "nd" 
    when 3  then "rd" 
    else   "th" 
    end 
    "%s (%d%s Century)" % [str, century, suffix] 
end 

centuryize "The American Revolution started in 1775." 
    # => "The American Revolution started in 1775. (18th Century)" 
centuryize "The Battle of Hastings took place in 1066." 
    #=> "The Battle of Hastings took place in 1066. (11th Century)" 
centuryize "Nero played the fiddle while Rome burned in AD 64." 
    #=> "Nero played the fiddle while Rome burned in AD 64. (1st Century)"