简体   繁体   English

Ruby Regex gsub! 不使用if

[英]Ruby Regex gsub! without using if

First of all, full disclosure, I am working on a homework assignment. 首先,要充分公开,我正在做作业。 The example I'm giving is not the exact problem, but will help me understand what I need to do. 我所举的例子并不是确切的问题,但是可以帮助我理解我需要做的事情。 I'm not looking for a spoon-fed answer but to understand what is going on. 我不是在寻找答案,而是要了解发生了什么。

I am trying to take a string such as: 我正在尝试采用如下字符串:

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

In this example I would like to return the same string, but with the appropriate century in parenthesis after 在此示例中,我想返回相同的字符串,但是在后面加上适当的百分号

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

I am able to group what I need using the following regex 我可以使用以下正则表达式将我需要的分组

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

It would be easy using grouping to say if \\2 == 1861 append appropriate century, but the specifications say no if statements may be used and I am very lost. 使用分组来表示if \\2 == 1861附加了适当的世纪是很容易的,但是规范说if可以使用语句则不if并且我非常迷失。 Also, the alternation I used in this example only works for the 2 years listed and I know that a better form of range-matching would have to be used to catch full centuries as opposed to those 2 single years. 另外,我在本示例中使用的替代方法仅适用于所列的两年,并且我知道,与过去的两年相比,必须使用更好的范围匹配形式来捕获整个世纪。

Firstly - how to remove the hardcoding of the years: 首先-如何删除年份的硬编码:

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

This should handle things for the next ~1k years. 这应该可以处理接下来的大约1000年。 If you know for a fact that the dates are restricted to given periods, you can be more specific. 如果您知道日期仅限于给定期间,则可以更具体。


For the other part - the century is just the first two digits plus one. 另一方面-世纪只是前两位数字加一位。 So split the year in two and increment. 因此,将年份一分为二并递增。

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

Note the usage of String#gsub with block due to the fact that we need to perform a transformation on one of the matched groups. 请注意将String#gsub与block一起使用,因为我们需要对匹配的组之一执行转换。


Update: if you want the centuries to be in words, you could use an array to store them. 更新:如果您希望将百年历史写成文字,则可以使用数组来存储它们。

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): Assuming you want to replace something completely different and you can't take advantage of number niceties like in the centuries example, implement the same general idea, just use a hash instead of array: 更新(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

Assuming the year is between 1 and 2099, you might do it as follows. 假设年份介于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)"

It would be easier if we could write "19th" 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