我正在使用Ruby on Rails應用程序。在我正在調用API的地方的一個應用程序中,它返回字符串爲Up 4.35% from Oct to Nov
。我的要求是當我在用戶界面上顯示時,我需要將其顯示爲Up 4.35% from October to November
。從Ruby中的字符串中提取月份名稱
有人能告訴我我該怎麼做?
我正在使用Ruby on Rails應用程序。在我正在調用API的地方的一個應用程序中,它返回字符串爲Up 4.35% from Oct to Nov
。我的要求是當我在用戶界面上顯示時,我需要將其顯示爲Up 4.35% from October to November
。從Ruby中的字符串中提取月份名稱
有人能告訴我我該怎麼做?
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"
與Date :: MONTHNAMES的好主意,但我會結合@ toro2k的評論MikDiet的答案更好的解決方案。 – 2014-10-09 14:59:45
確實。更新爲使用這些。 – 2014-10-09 15:38:31
對'dates.keys.join('|')'*非常小心。 – 2014-10-09 16:13:24
您可以使用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"
您可以將散列作爲'gsub'的第二個參數傳遞,不需要該塊:''abc'.gsub(/ a | b /,'a'=>'x','b'=> 'y')#=>「xyc」'。 – toro2k 2014-10-09 14:09:45
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)
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"
人不重視這個特殊的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-zA-Z0-9_]
,AKA \w
,並且單詞中斷是先前的非單詞字符和單詞字符之間的分界線。不這樣做是各種人類苦難的根源;子串將匹配沒有\b
,你可以得到各種有趣的替代品。(?:...)
定義了一個非捕獲組,這是一個很好的方式來找到一系列的替代模式,在這種情況下,它是三個字母,縮短月份名稱的列表。Regexp.union
是一個有用的方法,它接受一個數組(在本例中爲散列的鍵),並將它們與|
(模式中的OR符號)分開。基本上這意味着任何鍵都可以匹配。source
是這個非常重要的部分。沒有它,編譯的正則表達式Regexp.union
的結果會插入到字符串中,以及可能導致衝突搜索的相關標誌。考慮這些差異:
/foo/i # => /foo/i
/#{ /foo/i }/ # => /(?i-mx:foo)/
/foo/i.source # => "foo"
/#{ /foo/i.source }/ # => /foo/
第一個是不區分大小寫的模式。第二種是嵌入區分大小寫的區分大小寫模式,但(?i-mx:
將其標記爲內部不敏感。除非你確定這是你想要的,否則這是一個等待中的錯誤。
source
返回沒有標誌的字符串化版本,所以最終的結果就是我們期望的結果。
我以前就被這個咬過,這是追查的主要痛點。
最後,Date類有一些預定義的常量,這將允許你不必像上面那樣長時間定義散列。這是爲了更明顯地表發生了什麼事,但爲了方便,你可以做這樣的事情:
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)/
注意樣品中使用的[1..-1]
。這是因爲數組中包含一個nil,它們的第一個值使得數組基於1而不是基於0的數組,因爲我們的查找樂趣,但是如果您嘗試使用數組來獲取模式,這可能會導致Ruby咆哮。
字符串格式是否總是像示例中那樣具有月份? – 2014-10-09 15:45:51