El uso de expresiones regulares en Ruby 1.8.7+:
p s.scan(/((\d)\2*)/).map(&:first)
#=> ["111", "22", "1"]
Esto funciona porque (\d)
capta cualquier dígito, y luego \2*
captura cero o más de lo que ese grupo (el segundo paréntesis de apertura) haya igualado. El (…)
externo es necesario para capturar la coincidencia completa como resultado en scan
. Por último, scan
solo devuelve:
[["111", "1"], ["22", "2"], ["1", "1"]]
... así que tenemos que correr a través y mantener sólo el primer elemento de cada matriz. En Rubí 1.8.6+ (que no tiene Symbol#to_proc
por conveniencia):
p s.scan(/((\d)\2*)/).map{ |x| x.first }
#=> ["111", "22", "1"]
Sin expresión regular, esto es una diversión (encaje cualquier char) que funciona en Ruby 1.9.2:
p s.chars.chunk{|c|c}.map{ |n,a| a.join }
#=> ["111", "22", "1"]
Aquí hay otra versión que debería funcionar incluso en Ruby 1.8.6:
p s.scan(/./).inject([]){|a,c| (a.last && a.last[0]==c[0] ? a.last : a)<<c; a }
# => ["111", "22", "1"]
lo que debe suceder cuando la entrada tiene caracteres que no sean dígitos, por ejemplo, '" 111aaa222 "' y '" 111aaa111 "'? – Phrogz