2010-08-19 100 views
12

串掃描結果的指標我想索引以及掃描結果獲取紅寶石

"abab".scan(/a/) 

我想不僅

=> ["a", "a"] 

而且指數那些匹配的

[1, 3] 

有什麼建議嗎?

+0

嗨 - 抱歉大量垃圾郵件,但http://area51.stackexchange.com/proposals/74083/korean-語言可以使用你,如果你不在那裏! – 2016-05-23 18:39:16

回答

19

試試這個:

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

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

謝謝,這工作! – adn 2010-08-19 09:26:32

+12

@託德的答案是對的。但是,如果您更願意避免使用像'$〜'這樣稍微隱蔽的特殊變量,那麼'Regexp.last_match'是等價的。即你可以說'Regexp.last_match.offset(0)[0]' – mikej 2010-08-19 13:53:12

+7

甚至是'Regexp.last_match.offset(0).first' – 2010-08-19 21:41:50

1

讓我吃驚,沒有類似String#scan這將返回MatchData對象的數組,類似於String#match任何方法。所以,如果你喜歡猴子打補丁,你可以與託德的解決方案結合本(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] 
+0

NoMethodError:undefined method'scan'for – Andy 2016-01-07 12:49:43

6

有一個疑難雜症看出來這裏,這取決於你所期望的行爲。

如果您在"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,它可能是長字符串更快。

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