¿Cómo puedo generar ceros a la izquierda en Ruby?

238

Estoy sacando un conjunto de archivos numerados de un script Ruby. Los números provienen de incrementar un contador, pero para que se clasifiquen bien en el directorio, me gustaría usar ceros a la izquierda en los nombres de archivo. En otras palabras

file_001 ...

en vez de

archivo_1

¿Hay una manera simple de agregar ceros al convertir un número a una cadena? (Sé que puedo hacer "si menos de 10 ... si menos de 100").

Nathan Long
fuente

Respuestas:

281

Si se conoce el número máximo de dígitos en el contador (por ejemplo, n = 3 para los contadores 1..876), puede hacer

str = "file_" + i.to_s.rjust(n, "0")
alex.zherdev
fuente
8
Je je, no es la mejor respuesta, pero no sabía nada sobre eso y he estado usando ruby ​​durante años. ¡Salud!
pauliephonic
Tengo que votar esto porque parece que% 03s rellena con espacios por alguna extraña razón (% 03d parece funcionar bien). Podría haber jurado C rellenado con ceros en ambos casos.
Nerdmaster
Finalmente cambié esto para que sea la respuesta aceptada porque es la más simple y fácil de recordar. %funciona pero tiene un propósito más general.
Nathan Long
inesperado pero más fácil
akostadinov
1
Vine aquí para saber cómo rellenar un número base 36. Esto funciona para eso, mientras que% parece que no lo hará. ¡Gracias!
Ethan Kaminski
344

Use el %operador con una cadena:

irb(main):001:0> "%03d" % 5
=> "005"

El lado izquierdo es una cadena de formato printf, y el lado derecho puede ser una lista de valores, por lo que podría hacer algo como:

irb(main):002:0> filename = "%s/%s.%04d.txt" % ["dirname", "filename", 23]
=> "dirname/filename.0023.txt"

Aquí hay una hoja de trucos en formato printf que puede ser útil para formar su cadena de formato. El formato printf es originalmente de la Cfunción printf, pero hay funciones de formateo similares disponibles en perl, ruby, python, java, php, etc.

Daniel Martin
fuente
1
¡Excelente! Entonces, "% s" significa "sustituir el enésimo valor aquí" y "% 03d" significa "sustituir un número aquí, agregando tantos ceros como sea necesario para convertirlo en un número de 3 dígitos". (Supongo que d significa "dígitos"). Ahora veo la documentación sobre esto ( ruby-doc.org/core/classes/String.html#M000770 ), pero es muy conciso y me gustaría un poco más de elaboración. .
Nathan Long
1
Agregué un enlace a una hoja de trucos en formato printf. "s" significa "cadena", "d" significa "número decimal". El "03" significa "pad a 3 caracteres con ceros"; "% 3d" se rellenaría a la izquierda con espacios.
Daniel Martin
2
Por cierto, esto es lo mismo que llamar Kernel#sprintf, que se documenta aquí: ruby-doc.org/core-1.9.3/Kernel.html#method-i-sprintf
Nathan Long
Agregando al comentario de @ NathanLong, el primer ejemplo en esta respuesta se escribiría como sprintf("%03d", 5).
Dennis
Esta debería ser la respuesta seleccionada.
Dan Barron
50

¿No puedes usar el formato de cadena del valor antes de concatenar el nombre del archivo?

"%03d" % number
Ólafur Waage
fuente
Creo que esta respuesta no agrega nada a la respuesta de @Daniel Martin, sin embargo, me gusta su simplicidad ...
svelandiag 03 de
3
Respondió en el mismo minuto que Daniel Martin, por lo que probablemente no se dio cuenta de la duplicación.
Kurt Peek
Esto es perfecto para utc_offset
Abel
30

Úselo String#nextcomo el contador.

>> n = "000"
>> 3.times { puts "file_#{n.next!}" }
file_001
file_002
file_003

next es relativamente 'inteligente', lo que significa que incluso puedes ir por

>> n = "file_000"
>> 3.times { puts n.next! }
file_001
file_002
file_003
testr
fuente
Gracias por señalar esto. Este es un método increíble.
Weston Ganger
9

Como se indica en las otras respuestas, "%03d" % numberfunciona bastante bien, pero va en contra de la guía de estilo rubocop ruby :

Favorezca el uso de sprintf y su formato de alias sobre el método String #% bastante críptico

Podemos obtener el mismo resultado de una manera más legible usando lo siguiente:

format('%03d', number)
Rodrigo Vasconcelos
fuente
1
Si su objetivo es aprender una característica oscura del lenguaje Ruby, use el alias format. Si su objetivo es hacer que su código sea fácil de entender, debe usarlo sprintfporque es parte de la biblioteca C estándar. Este nombre se usa en todos los lenguajes de programación. Más personas entienden lo que sprintfhace, en comparación con el número que sabe que formates un alias para ello. El hecho de que algo sea parte de RuboCop no lo hace intrínsecamente correcto o incorrecto. Elija las reglas que tengan más sentido para su proyecto. '%03d' % numberEs aún más fácil de leer.
Tilo
1
Pasé por este mismo ciclo, cambiando "%02d" % numa sprintf(...), luego a format(...)la sugerencia de RuboCop. Entonces decidí que sprintfera más convencional que format, así que actualicé rubocop.yml con Style/FormatString: EnforcedStyle: sprintfy ahora duermo bien por la noche.
David Hempy
1

filenames = '000'.upto('100').map { |index| "file_#{index}" }

Salidas

[file_000, file_001, file_002, file_003, ..., file_098, file_099, file_100]

Ivan
fuente