2014-10-09 63 views
0

我正在使用Ruby on Rails應用程序。在我正在調用API的地方的一個應用程序中,它返回字符串爲Up 4.35% from Oct to Nov。我的要求是當我在用戶界面上顯示時,我需要將其顯示爲Up 4.35% from October to November從Ruby中的字符串中提取月份名稱

有人能告訴我我該怎麼做?

+0

字符串格式是否總是像示例中那樣具有月份? – 2014-10-09 15:45:51

回答

2

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

與Date :: MONTHNAMES的好主意,但我會結合@ toro2k的評論MikDiet的答案更好的解決方案。 – 2014-10-09 14:59:45

+0

確實。更新爲使用這些。 – 2014-10-09 15:38:31

+0

對'dates.keys.join('|')'*非常小心。 – 2014-10-09 16:13:24

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" 
+3

您可以將散列作爲'gsub'的第二個參數傳遞,不需要該塊:''abc'.gsub(/ a | b /,'a'=>'x','b'=> 'y')#=>「xyc」'。 – toro2k 2014-10-09 14:09:45

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) 
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" 
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-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咆哮。

相關問題