Extrayendo los últimos n caracteres de una cadena ruby

105

Para obtener los últimos ncaracteres de una cadena, asumí que podrías usar

ending = string[-n..-1]

pero si la cadena tiene menos de nletras, obtienes nil.

¿Qué soluciones alternativas están disponibles?

Antecedentes : las cadenas son ASCII sin formato, tengo acceso a ruby ​​1.9.1 y estoy usando Plain Old Ruby Objects (sin marcos web).

Andrew Grimm
fuente

Respuestas:

99

Aquí tienes un trazador de líneas, puedes poner un número mayor que el tamaño de la cuerda:

"123".split(//).last(5).to_s

Para ruby ​​1.9+

"123".split(//).last(5).join("").to_s

Para ruby ​​2.0+, join devuelve una cadena

"123".split(//).last(5).join
Gareve
fuente
19
Si está usando una versión reciente de Ruby, puede usar en charslugar de dividir.
Andrew Grimm
1
Usé "12345678910" .split (//). Last (7) .join.to_s
Hard-Boiled Wonderland
@ Hard-BoiledWonderland joinfunciona. No creo que necesites el último to_ssi usas unirse.
Andrew Grimm
@AndrewGrimm Tienes razón, para ese caso usé lo anterior con Nokogiri n.xpath('ReferenceID').inner_text.split(//).last(7).join.to_s.to_i. Necesitaba los to_s para realizar el to_i para extraer el valor numérico.
Hard-Boiled Wonderland
Falta .join ; ahora devuelve una matriz de cadenas. En su lugar debería ser "123".split(//).last(5).join(Ruby 2.0.0)
Pavel Nikolov
115

Bueno, la solución más fácil que se me ocurre es:

ending = str[-n..-1] || str

(EDITAR: el oroperador tiene una precedencia menor que la asignación, así que asegúrese de usarlo ||)

perimosocordiae
fuente
+1 ... Creo que esta forma es más fácil de leer que string.reverse[0..n].reverse, lo que me da un segundo de "espera, ¿por qué está haciendo eso?" (o lo haría si no lo estuviera leyendo en el contexto de esta pregunta)
Arkaaito
4
Buena respuesta, pero debería ser en ||lugar de or, o poner paréntesis str[-n..-1] or str.
Andrew Grimm
Buena respuesta, pero no me gusta que ruby ​​no trate s [-inf ..- 1] igual que x [0..inf]
klochner
Gracias por señalar el problema de la precedencia del operador, Andrew. Me atrapa todo el tiempo.
perimosocordiae
@perimosocordiae, no eres el único. stackoverflow.com/questions/372652/…
Andrew Grimm
51

En Ruby recto (sin rieles), puede hacer

string.chars.last(n).join

Por ejemplo:

2.4.1 :009 > a = 'abcdefghij'
 => "abcdefghij"
2.4.1 :010 > a.chars.last(5).join
 => "fghij"
2.4.1 :011 > a.chars.last(100).join
 => "abcdefghij"

Si está utilizando Ruby on Rails, puede llamar a métodos firsty lasten un objeto de cadena. Se prefieren estos métodos porque son sucintos e intuitivos.

Por ejemplo:

[1] pry(main)> a = 'abcdefg'                                                                                                                
 => "abcdefg"
[2] pry(main)> a.first(3)                                                                                                                   
 => "abc"
[3] pry(main)> a.last(4)                                                                                                                    
 => "defg"
Zack Xu
fuente
1
Ruby no implica Rails.
Volte
14
ending = string.reverse[0...n].reverse
Andrew Grimm
fuente
Este es el mejor enfoque que veo en esta página que satisface el requisito de poder proporcionar una longitud de carácter final que exceda la longitud total de la cadena.
Rob.Kachmar
1
Por ejemplo, si tiene la intención de tomar los últimos 3 caracteres de un grupo de picaduras como "abcde", "ab" y "a". Esta técnica dará como resultado que "cde", "ab" y "a" utilicen el mismo código para cada uno. "abcde".reverse[0,3].reverse>>> "cde" "ab".reverse[0,3].reverse>>> "ab" "a".reverse[0,3].reverse>>> "a"
Rob.Kachmar
9

Puede utilizar el siguiente código:

string[string.length-n,string.length]
rurkss
fuente
1
solo código: las respuestas no siempre son útiles. explicar por qué / cómo este código es la solución sería genial
ry8806
6

Para obtener los últimos n caracteres de una cadena, puede hacer esto

a [-n, n] si a es la matriz.

Aquí tienes un ejemplo si quieres uno.

ruby-1.9.2-p180: 006> a = "911234567890"

=> "911234567890"

ruby-1.9.2-p180: 009> a [-5,5]

=> "67890"

ruby-1.9.2-p180: 010> a [-7,7]

=> "4567890"

Sunil
fuente
Si el número es demasiado grande, nilse devuelve, que es lo que esta pregunta trataba de evitar específicamente.
Andrew Grimm
Buena respuesta. Limpiar.
Volte
¿Por qué esto está recibiendo votos positivos? Tiene exactamente el mismo problema que lo que el OP estaba preguntando cómo solucionarlo.
jeffdill2
5

¿Has probado una expresión regular?

string.match(/(.{0,#{n}}$)/)
ending=$1

La expresión regular captura tantos caracteres como pueda al final de la cadena, pero no más de n. Y lo guarda en $ 1.

EmFi
fuente
1

Mejora en la respuesta de EmFi.

string[/.{,#{n}}\z/m]
sawa
fuente