2010-08-19 7 views
12

Quiero obtener el índice, así como los resultados de una exploraciónObtener el índice de los resultados del análisis de cadenas en ruby ​​

"abab".scan(/a/) 

me gustaría tener no sólo

=> ["a", "a"] 

sino también el índice de esos partidos

[1, 3] 

¿Alguna sugerencia?

+0

Hi - lo siento por el spam masivo pero http://area51.stackexchange.com/proposals/74083/korean- ¡el lenguaje podría usarte si no estás allí ya! –

Respuesta

19

Prueba esto:

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

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

gracias, eso funciona! – adn

+12

@ La respuesta de Todd es correcta. Sin embargo, si prefiere evitar el uso de las variables especiales ligeramente crípticas como '$ ~', entonces 'Regexp.last_match' es equivalente. es decir, puede decir 'Regexp.last_match.offset (0) [0]' – mikej

+7

o incluso 'Regexp.last_match.offset (0) .first' –

1

Me sorprendió que no hay ningún método similar al String#scan que volver gama de MatchData objetos, similar a String#match. Por lo tanto, si te gusta el mono-aplicación de parches, puede combinar esto con una solución de Todd (Enumerator se introduce en el apartado 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: método indefinido 'scan 'para – Andy

6

Hay una Gotcha a tener en cuenta aquí, dependiendo del comportamiento que espera.

Si busca /dad/ en "dadad" sólo se obtendría [["dad",0]] PORQUE scan anticipos al final de cada partido cuando se encuentra uno (que está mal para mí).

me ocurrió con esta alternativa:

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 

Si quería también se puede hacer una cosa similar con StringScanner de la librería estándar, podría ser más rápido para las cadenas largas.

4

muy similar a lo que ha dicho @jim y trabaja un poco mejor para cadenas más largas:

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 
Cuestiones relacionadas