字符串为:1/9/2017
我的正则表达式是:/([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/
这是我的代码行:
def session_formatter(string)
if string =~ /([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/
year = $2
if $1 =~ /8|9|10|11/
"Fall " + year
elsif $1 =~ /1|2|3/
"Spring " + year
else
string
end
end
end
我已1/9/2017
返回而不是Spring 2017
,我无法弄清楚原因。有任何想法吗?
答案 0 :(得分:2)
而不是处理我使用的正则表达式:
str = '1/9/2017'
mm, dd, yyyy = str.split('/')
case mm.to_i
when 1, 2, 3
"Spring #{yyyy}"
when 8, 9, 10
"Fall #{yyyy}"
else
str
end
# => "Spring 2017"
正则表达式很棒,但人们喜欢使用它们,因此忽略了更简单地完成任务的方式。并不是所有的东西都是等待用正则锤击打的指甲。
/
上的拆分可以降低视觉噪音,使用to_i
可以更轻松地阅读和理解when
正在做的事情。
或者,使用Date类,它具有各种优点:
require 'date'
str = '1/9/2017'
date = Date.strptime(str, '%m/%d/%Y')
case date.month
when 1, 2, 3
"Spring #{date.year}"
when 8, 9, 10
"Fall #{date.year}"
else
str
end
# => "Spring 2017"
我使用strptime
因为日期格式在全球范围内并不一致。作为一种国际语言,Ruby使用最常见的格式dd / mm / yyyy用于Date.parse(...)
,这在解析基于美国的日期时可能会遇到问题。而strptime
让我强迫解析器使用基于美国的mm / dd / yyyy形式:
require 'date'
Date.strptime('31/12/2001', '%d/%m/%Y') # => #<Date: 2001-12-31 ((2452275j,0s,0n),+0s,2299161j)>
Date.strptime('31/12/2001', '%m/%d/%Y') # => ArgumentError: invalid date
# ~> ArgumentError
# ~> invalid date
请注意,第一个示例成为此特定问题的牺牲品。处理日期时,如果您允许用户输入日期作为自由格式字符串,那么您知道用户来自哪里非常重要,因此您至少可以猜测这些值的顺序。更好,更多用户 - 友好的解决方案是使用具有某种日期选择器的表单,这会强制订单进入您的代码所期望的。错误地处理日期会导致涉及时间或金钱的计算造成重大破坏,您只是不希望发生这种情况。
如果日期是文件中文本的一部分,则处理起来会更容易一些,因为它应该一致地格式化,但顺序仍然很重要。
如果确实坚持使用模式,我会这样做:
str = '1/9/2017'
/(?<mm>[0-9]{1,2})\/[0-9]{1,2}\/(?<yyyy>[0-9]{4})/ =~ str
mm # => "1"
yyyy # => "2017"
case mm.to_i
when 1, 2, 3
"Spring #{yyyy}"
when 8, 9, 10
"Fall #{yyyy}"
else
str
end
# => "Spring 2017"
或者,为了增加乐趣:
str = '1/9/2017'
matches = /(?<mm>[0-9]{1,2})\/[0-9]{1,2}\/(?<yyyy>[0-9]{4})/.match(str)
mm, yyyy = matches[:mm], matches[:yyyy]
case mm.to_i
when 1, 2, 3
"Spring #{yyyy}"
when 8, 9, 10
"Fall #{yyyy}"
else
str
end
# => "Spring 2017"
请参阅Ruby的Regexp文档,了解“命名捕获组”。
答案 1 :(得分:1)
您正在使用后续的正则表达式检查重写$1
变量。将其分配给单独的变量并用于进一步检查。
def session_formatter(string)
if string =~ /([0-9]{1,2})\/[0-9]{1,2}\/([0-9]{4})/
year = $2
month = $1
if month =~ /8|9|10|11/
"Fall " + year
elsif month =~ /1|2|3/
"Spring " + year
else
string
end
end
end
请参阅Ruby demo
答案 2 :(得分:0)
这是在regex中使用命名分组和简单哈希查找的另一种解决方案:
TIME_OF_YEAR = { 'Winter' => [12,1,2],
'Spring' => [3,4,5],
'Summer' => [6,7,8],
'Fall' => [9,10,11]}
def session_formatter(string)
string.match(/(?<month>[0-9]{1,2})\/[0-9]{1,2}\/(?<year>[0-9]{4})/) do |m|
TIME_OF_YEAR.detect {|_,v| v.include? (m[:month].to_i)}.first + " #{m[:year]}"
end
end
dates = ["1/9/2017", "2/9/2017", "3/9/2017", "4/9/2017", "5/9/2017", "6/9/2017", "7/9/2017", "8/9/2017",
"9/9/2017", "10/9/2017", "11/9/2017", "12/9/2017"]
puts dates.map {|d| session_formatter(d)}
这使用正则表达式中的命名分组和匹配的块形式,允许您以简洁的方式查找TIME_OF_YEAR
哈希中的一年中的时间。