Get index of string scan results in ruby

前端 未结 4 1132
半阙折子戏
半阙折子戏 2020-12-10 03:13

I want to get the index as well as the results of a scan

\"abab\".scan(/a/)

I would like to have not only

=> [\"a\", \"a         


        
相关标签:
4条回答
  • 2020-12-10 03:32

    It surprised me that there isn't any method similar to String#scan which would return array of MatchData objects, similar to String#match. So, if you like monkey-patching, you can combine this with Todd's solution (Enumerator is introduced in 1.9):

    class Regexp
      def scan str
        Enumerator.new do |y|
          str.scan(self) do
            y << Regexp.last_match
          end
        end
      end
    end
    #=> nil
    /a/.scan('abab').map{|m| m.offset(0)[0]}
    #=> [0, 2]
    
    0 讨论(0)
  • 2020-12-10 03:34

    Very similar to what @jim has said and works a bit better for longer strings:

    def matches str, pattern
        arr = []
        while (str && (m = str.match pattern))      
            offset = m.offset(0).first 
            arr << offset + (arr[-1] ? arr[-1] + 1 : 0)
            str = str[(offset + 1)..-1]
        end
        arr
    end
    
    0 讨论(0)
  • 2020-12-10 03:48

    Try this:

    res = []
    "abab".scan(/a/) do |c|
      res << [c, $~.offset(0)[0]]
    end
    
    res.inspect # => [["a", 0], ["a", 2]]
    
    0 讨论(0)
  • 2020-12-10 03:57

    There's a gotcha to look out for here, depending on the behaviour you expect.

    If you search for /dad/ in "dadad" you'd only get [["dad",0]] because scan advances to the end of each match when it finds one (which is wrong to me).

    I came up with this alternative:

    def scan_str(str, pattern)
      res = []
      (0..str.length).each do |i|
        res << [Regexp.last_match.to_s, i] if str[i..-1] =~ /^#{pattern}/
      end
      res
    end
    

    If you wanted you could also do a similar thing with StringScanner from the standard library, it might be faster for long strings.

    0 讨论(0)
提交回复
热议问题