【问题标题】:Get index of string scan results in ruby在 ruby​​ 中获取字符串扫描结果的索引
【发布时间】:2011-04-01 00:24:29
【问题描述】:

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

"abab".scan(/a/)

我想要的不仅仅是

=> ["a", "a"]

还有那些匹配的索引

[1, 3]

有什么建议吗?

【问题讨论】:

标签: ruby indexing


【解决方案1】:

试试这个:

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

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

【讨论】:

  • @Todd 的回答是正确的。但是,如果您希望避免使用像 $~ 这样的稍微神秘的特殊变量,那么 Regexp.last_match 是等价的。即你可以说Regexp.last_match.offset(0)[0]
  • 甚至Regexp.last_match.offset(0).first
  • 对于那些想知道这些方法如何工作的人,请参阅MatchData#offsetRegexp::last_match
【解决方案2】:

这里有一个问题需要注意,具体取决于您所期望的行为。

如果您在"dadad" 中搜索/dad/,您只会得到[["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 做类似的事情,对于长字符串可能会更快。

【讨论】:

    【解决方案3】:

    与@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
    

    【讨论】:

      【解决方案4】:

      令我惊讶的是,没有任何类似于String#scan 的方法可以返回MatchData 对象的数组,类似于String#match。所以,如果你喜欢猴子补丁,你可以将它与 Todd 的解决方案结合起来(Enumerator 在 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]
      

      【讨论】:

      • NoMethodError: undefined method `scan' for
      猜你喜欢
      • 2012-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 2011-06-28
      • 1970-01-01
      • 2021-07-19
      • 2012-01-31
      相关资源
      最近更新 更多