获取ruby中的字符串扫描结果索引

时间:2010-08-19 09:03:06

标签: ruby indexing

我想获取索引以及扫描结果

"abab".scan(/a/)

我不仅要

=> ["a", "a"]

还有那些比赛的索引

[1, 3]

任何建议?

4 个答案:

答案 0 :(得分:23)

试试这个:

res = []
"abab".scan(/a/) do |c|
  res << [c, $~.offset(0)[0]]
end

res.inspect # => [["a", 0], ["a", 2]]

答案 1 :(得分:6)

根据你期望的行为,这里有一个值得关注的问题。

如果您在/dad/中搜索"dadad",则只会获得[["dad",0]],因为scan会在找到一个匹配时前进到每个匹配的结尾(这是错误的我)。

我想出了这个替代方案:

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

如果你想要也可以在标准库中使用StringScanner做类似的事情,那么长字符串可能会更快。

答案 2 :(得分:4)

非常类似于@jim所说的并且对于更长的字符串效果更好:

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

答案 3 :(得分:1)

令我感到惊讶的是,没有任何类似于String#scan的方法会返回MatchData个对象的数组,类似于String#match。所以,如果你喜欢猴子修补,你可以将它与Todd的解决方案结合起来(1.9中引入了Enumerator):

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]