繁体   English   中英

Ruby Regex gsub! 不使用if

[英]Ruby Regex gsub! without using if

首先,要充分公开,我正在做作业。 我所举的例子并不是确切的问题,但是可以帮助我理解我需要做的事情。 我不是在寻找答案,而是要了解发生了什么。

我正在尝试采用如下字符串:

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

在此示例中,我想返回相同的字符串,但是在后面加上适当的百分号

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

我可以使用以下正则表达式将我需要的分组

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

使用分组来表示if \\2 == 1861附加了适当的世纪是很容易的,但是规范说if可以使用语句则不if并且我非常迷失。 另外,我在本示例中使用的替代方法仅适用于所列的两年,并且我知道,与过去的两年相比,必须使用更好的范围匹配形式来捕获整个世纪。

首先-如何删除年份的硬编码:

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

这应该可以处理接下来的大约1000年。 如果您知道日期仅限于给定期间,则可以更具体。


另一方面-世纪只是前两位数字加一位。 因此,将年份一分为二并递增。

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

请注意将String#gsub与block一起使用,因为我们需要对匹配的组之一执行转换。


更新:如果您希望将百年历史写成文字,则可以使用数组来存储它们。

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

更新(2):假设您要替换完全不同的内容,并且无法利用像世纪示例中那样的数字优点,实现相同的基本思想,仅使用哈希而不是数组:

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

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

假设年份介于1到2099之间,则可以按以下方式进行操作。

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)"

如果我们能写出“ 19世纪”,那会更容易。

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)" 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM