从Ruby中的字符串中提取月份名称

时间:2014-10-09 13:22:44

标签: ruby-on-rails ruby ruby-on-rails-4

我正在使用Ruby on Rails应用程序。在我正在调用API的地方的应用程序中,我将字符串作为Up 4.35% from Oct to Nov返回给我。我的要求是当我在用户界面上显示时,我需要将其显示为Up 4.35% from October to November

有人可以告诉我该怎么做?

5 个答案:

答案 0 :(得分:3)

Date::MONTHNAMES也许可以帮到你。如果它们总是3个字符缩短版本的月份,您可以构建一个哈希来帮助:

dates = Date::MONTHNAMES.compact.map { |m| [m[0..2], m] }.to_h

然后在别处使用它:

text = 'Up 4.35% from Oct to Nov'
text.gsub(/#{dates.keys.join('|')}/, dates)
=> "Up 4.35% from October to November"

答案 1 :(得分:2)

您可以使用gsub

只需延长我所有月份的例子:

"Up 4.35% from Oct to Nov".gsub(/Oct|Nov/) do |s| 
  {'Oct' => 'October', 'Nov' => 'November'}[s]
end
# => "Up 4.35% from October to November" 

答案 2 :(得分:1)

您需要

String#sub

试试这个:

a = "Up 4.35% from Oct to Nov"
a.sub('Oct', 'October').sub('Nov', 'November') # you can continue with other months
#=> "Up 4.35% from October to November"

答案 3 :(得分:1)

人们不会注意这种特殊的gsub能力,所以请冥想:

SHORT_TO_LONG_MONTH_NAMES = %w[
  January
  February
  March
  April
  May
  June
  July
  August
  September
  October
  November
  December
].map{ |m| [m[0, 3], m] }.to_h
# => {"Jan"=>"January", "Feb"=>"February", "Mar"=>"March", "Apr"=>"April", "May"=>"May", "Jun"=>"June", "Jul"=>"July", "Aug"=>"August", "Sep"=>"September", "Oct"=>"October", "Nov"=>"November", "Dec"=>"December"}

SHORT_TO_LONG_MONTH_NAMES_REGEX = /\b(?:#{ Regexp.union(SHORT_TO_LONG_MONTH_NAMES.keys).source })\b/
# => /\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b/

str = 'Up 4.35% from Oct to Nov'

str.gsub(SHORT_TO_LONG_MONTH_NAMES_REGEX, SHORT_TO_LONG_MONTH_NAMES)
# => "Up 4.35% from October to November"

以简洁的方式去除输出结果,以快速搜索和替换文档:

SHORT_TO_LONG_MONTH_NAMES = %w[
  January
  February
  March
  April
  May
  June
  July
  August
  September
  October
  November
  December
].map{ |m| [m[0, 3], m] }.to_h

SHORT_TO_LONG_MONTH_NAMES_REGEX = /\b(?:#{ Regexp.union(SHORT_TO_LONG_MONTH_NAMES.keys).source })\b/

str = 'Up 4.35% from Oct to Nov'

str.gsub(SHORT_TO_LONG_MONTH_NAMES_REGEX, SHORT_TO_LONG_MONTH_NAMES)
# => "Up 4.35% from October to November"

旧红宝石没有to_h所以你可以使用它:

SHORT_TO_LONG_MONTH_NAMES = Hash[%w[
  January
  February
  March
  April
  May
  June
  July
  August
  September
  October
  November
  December
].map{ |m| [m[0, 3], m] }]
# => {"Jan"=>"January", "Feb"=>"February", "Mar"=>"March", "Apr"=>"April", "May"=>"May", "Jun"=>"June", "Jul"=>"July", "Aug"=>"August", "Sep"=>"September", "Oct"=>"October", "Nov"=>"November", "Dec"=>"December"}

分解正则表达式模式生成:

SHORT_TO_LONG_MONTH_NAMES_REGEX = /\b(?:#{ Regexp.union(SHORT_TO_LONG_MONTH_NAMES.keys).source })\b/
  • \b是一个分词或词边界,意思是单词的开头或结尾。 A"字"是字符集[a-zA-Z0-9_],AKA \w,字断点是前一个非单词字符和单词字符之间的分界线。没有做到这一点是各种人类苦难的根源;子字符串将在没有\b的情况下匹配,因此您可以获得各种有趣的替换。
  • (?:...)定义了一个非捕获组,这是查找一系列备用模式的好方法,在这种情况下,它是三个字母缩短的月份名称列表。
  • Regexp.union是一个有用的方法,它接受一个数组,在本例中是哈希的键,并用|分隔它们,Regexp.union是模式中的OR符号。基本上它意味着任何键都可以匹配。
  • source是其中非常重要的一部分。如果没有它,/foo/i # => /foo/i /#{ /foo/i }/ # => /(?i-mx:foo)/ /foo/i.source # => "foo" /#{ /foo/i.source }/ # => /foo/ 的结果(它是一个编译的正则表达式)将被插入到字符串中,以及其相关的标志,这可能导致冲突的搜索。考虑一下这些之间的区别:

    (?i-mx:

    第一种是不区分大小写的模式。第二种是嵌入在区分大小写的情况下的不区分大小写的模式,但source在内部将其标记为不敏感。这是一个等待的错误,除非你确定这是你想要的。

    require 'date' Date::ABBR_MONTHNAMES.zip(Date::MONTHNAMES)[1..-1].to_h # => {"Jan"=>"January", "Feb"=>"February", "Mar"=>"March", "Apr"=>"April", "May"=>"May", "Jun"=>"June", "Jul"=>"July", "Aug"=>"August", "Sep"=>"September", "Oct"=>"October", "Nov"=>"November", "Dec"=>"December"} Hash[Date::ABBR_MONTHNAMES.zip(Date::MONTHNAMES)[1..-1]] # => {"Jan"=>"January", "Feb"=>"February", "Mar"=>"March", "Apr"=>"April", "May"=>"May", "Jun"=>"June", "Jul"=>"July", "Aug"=>"August", "Sep"=>"September", "Oct"=>"October", "Nov"=>"November", "Dec"=>"December"} /\b(?:#{ Regexp.union(Date::ABBR_MONTHNAMES[1..-1]).source }\b)/ # => /\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec\b)/ 返回没有标志的模式的字符串化版本,因此最终结果是我们实际期望的结果。

之前我已经被咬过了,追踪是一件很大的痛苦。

最后,Date类有一些预定义的常量,这样你就不必像我上面那样用long-hand定义哈希。这是为了明确发生了什么,但为方便起见,你可以做以下事情:

[1..-1]

请注意在样本中使用{{1}}。这是因为为了我们的查找乐趣,数组包含第一个值的nil,以使数组基于1而不是基于0,但如果您尝试使用数组,这会使Ruby嚎叫对于模式。

答案 4 :(得分:0)

def replace(string)
    string.gsub("Jan", "January").gsub("Feb", "February").gsub("Mar", "March").gsub("Apr", "April").gsub("Jul", "July").gsub("Aug", "August").gsub("Sep", "September").gsub("Oct", "October").gsub("Nov", "November").gsub("Dec", "December")
end

str = "Up 4.35% from Oct to Nov"

最后,只需调用函数:

replace(str)