在“综合Ruby编程课程”电子书中,我遇到了一个章节,作者(Jordan Hudgens)描述了这一章:
“我们要尝试的最后一件事是返回句子中的所有整数值。”
他是这样做的:
string = "The quick 12 brown foxes jumped over 10 lazy dogs"
p string.to_enum(:scan, /\d+/).map { Regexp.last_match }
它返回:
=> [#<MatchData "3">, #<MatchData "34">, #<MatchData "23">]
我想知道为什么/何时,可以使用这个Regexp.last_match
或更好地说 - 为什么这种方式不比以下方式更有效:
p string.to_enum(:scan, /\d+/).map { |i| p i }
这只输出一个整数数组,对我来说似乎是一种更有效的方法来获取这些数字..
任何人都可以解释一下作者选择Regesp.last_match
的原因可能是什么?
答案 0 :(得分:1)
这是一个很好的技巧(读:hack)。
string = "The quick 12 brown foxes jumped over 10 lazy dogs"
p string.to_enum(:scan, /\d+/).map { Regexp.last_match }
事情是yield
内MatchData
String#scan
p string.to_enum(:scan, /\d+/).map { |i| p i }
个实例没有方便的方法。
p string.to_enum(:scan, /\d+/).map(&:itself) # or { |i| i } # or .to_a
没有多大意义,你可能意味着:
p string.scan(/\d+/)
甚至
extension Date {
public var startOfQuarter: Date {
let startOfMonth = Calendar.current.date(from: Calendar.current.dateComponents([.year, .month], from: Calendar.current.startOfDay(for: self)))!
var components = Calendar.current.dateComponents([.month, .day, .year], from: startOfMonth)
let newMonth: Int
switch components.month! {
case 1,2,3: newMonth = 1
case 4,5,6: newMonth = 4
case 7,8,9: newMonth = 7
case 10,11,12: newMonth = 10
default: newMonth = 1
}
components.month = newMonth
return Calendar.current.date(from: components)!
}
}
结果不同;后者返回 strings ,而前者是返回MatchData
个实例的方法。
答案 1 :(得分:1)
如果你想要一个MatchData
个实例的枚举器,这里有一个更详细但可能更清晰的解决方案:
class String
def matches(regex)
position = 0
Enumerator.new do |yielder|
while match = regex.match(self, position)
yielder << match
position = match.end(0)
end
end
end
end
string = 'The quick 12 brown foxes jumped over 10 lazy dogs'
p string.matches(/\d+/).to_a
# [#<MatchData "12">, #<MatchData "10">]
p (2**1000000).to_s.matches(/(\d)\1{5}/).first(2)
# [#<MatchData "444444" 1:"4">, #<MatchData "888888" 1:"8">]
如果您不想使用String
补丁,可以在Regex
中定义此方法,也可以使用string
和regex
作为独立方法定义此方法作为参数。