¿Cuál es una forma eficiente de repetir una cadena hasta una longitud determinada? Ej: repeat('abc', 7) -> 'abcabca'
Este es mi código actual:
def repeat(string, length):
cur, old = 1, string
while len(string) < length:
string += old[cur-1]
cur = (cur+1)%len(old)
return string
¿Hay una forma mejor (más pitónica) de hacer esto? ¿Tal vez utilizando la comprensión de la lista?
La respuesta de Jason Scheirer' es correcta, pero podría utilizar algo más de exposición.
En primer lugar, para repetir una cadena un número entero de veces, puede utilizar la multiplicación sobrecargada:
>>> 'abc' * 7
'abcabcabcabcabcabcabc'
Así que, para repetir una cadena hasta que sea al menos tan larga como la longitud que quieras, calcula el número apropiado de repeticiones y ponlo en el lado derecho de ese operador de multiplicación:
def repeat_to_at_least_length(s, wanted):
return s * (wanted//len(s) + 1)
>>> repeat_to_at_least_length('abc', 7)
'abcabcabc'
A continuación, puede recortar a la longitud exacta que desea con una rebanada de la matriz:
def repeat_to_length(s, wanted):
return (s * (wanted//len(s) + 1))[:wanted]
>>> repeat_to_length('abc', 7)
'abcabca'
Alternativamente, como se sugiere en pillmod's respuesta que probablemente nadie se desplaza hacia abajo lo suficiente como para notar, puede utilizar divmod
para calcular el número de repeticiones completas necesarias, y el número de caracteres extra, todo a la vez:
def pillmod_repeat_to_length(s, wanted):
a, b = divmod(wanted, len(s))
return s * a + s[:b]
¿Qué es mejor? Hagamos una prueba:
>>> import timeit
>>> timeit.repeat('scheirer_repeat_to_length("abcdefg", 129)', globals=globals())
[0.3964178159367293, 0.32557755894958973, 0.32851039397064596]
>>> timeit.repeat('pillmod_repeat_to_length("abcdefg", 129)', globals=globals())
[0.5276265419088304, 0.46511475392617285, 0.46291469305288047]
Así, la versión de pillmod'es algo así como un 40% más lenta, lo cual es una pena, ya que personalmente creo que es mucho más legible. Hay varias razones posibles para esto, comenzando con su compilación a cerca de 40% más instrucciones de código de bytes.
Nota: estos ejemplos utilizan el nuevo operador //
para truncar la división de enteros. Esto es a menudo llamado una característica de Python 3, pero según PEP 238, fue introducido en Python 2.2. Sólo tienes que usarla en Python 3 (o en módulos que tengan from __future__ import division
) pero puedes usarla de todas formas.
def repeat_to_length(string_to_expand, length):
return (string_to_expand * ((length/len(string_to_expand))+1))[:length]
Para python3:
def repeat_to_length(string_to_expand, length):
return (string_to_expand * (int(length/len(string_to_expand))+1))[:length]
Qué tal cadena * (longitud / len(cadena)) + cadena[0:(longitud % len(cadena))]