2010-08-19 15 views
12

Chcę dostać indeks, jak również wyniki skanowaniaZdobądź indeks ciąg wyników skanowania w Ruby

"abab".scan(/a/) 

chciałbym mieć nie tylko

=> ["a", "a"] 

ale także indeks z tych meczów

[1, 3] 

wszelkie sugestie?

+0

Hi - przepraszam za spam, ale http://area51.stackexchange.com/proposals/74083/korean- masywnego język może cię wykorzystać, jeśli już tam nie jesteś! –

Odpowiedz

19

Spróbuj tego:

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

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

dzięki, to działa! – adn

+12

@ odpowiedzi Todda ma rację. Jednak jeśli wolisz uniknąć stosując nieco tajemnicze zmiennych specjalnych, takich jak '$ ~' 'Regexp.last_match' następnie jest równoważna. tzn. można powiedzieć: "Regexp.last_match.offset (0) [0]" – mikej

+7

lub nawet "Regexp.last_match.offset (0) .pierwszy" –

1

Zaskoczyło mnie, że nie istnieje jakakolwiek metoda podobna do String#scan która zwróci tablicę MatchData obiektów, podobny do String#match. Tak więc, jeśli chcesz małpa-łatanie, to można połączyć z roztworem Todda (Enumerator jest wprowadzony w 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: niezdefiniowana metoda "scan" dla – Andy

6

Nie ma haczyka, aby zwrócić uwagę tutaj, w zależności od zachowania się spodziewać.

Jeśli szukasz /dad/ w "dadad" można dostać tylko [["dad",0]] ponieważ scan zaliczek na koniec każdego meczu, gdy znajdzie (co jest nie tak ze mną).

wymyśliłem tej alternatywy:

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 

Jeśli chciałeś można również zrobić coś podobnego z StringScanner z biblioteki standardowej, może być szybsze dla długich ciągów.

4

Bardzo podobny do tego, co powiedział i @jim działa nieco lepiej dla dłuższych ciągów:

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 
Powiązane problemy