Regexp.last_match - зачем это полезно?
В книге " Всеобъемлющее рубиновое программирование курса" я столкнулся с главой, где автор (Джордан Хадженс) описывает это как:
"Последнее, что мы собираемся попробовать, - вернуть все целые значения из предложения".
И он делает это так:
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
?
Ответы
Ответ 1
Это отличный трюк (читай: взломать).
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
внутри 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+/)
Результаты отличаются друг от друга; последний возвращает строки, а первый - способ вернуть MatchData
экземпляры.
Ответ 2
Здесь более подробное, но, возможно, более чистое решение, если вы хотите, чтобы перечисление 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
.