La respuesta de Jason Scheirer es correcta, pero podría usar un poco más de exposición.
En primer lugar, para repetir una cadena un número entero de veces, puede usar la multiplicación sobrecargada:
>>> 'abc' * 7
'abcabcabcabcabcabcabc'
Entonces, para repetir una cadena hasta que sea al menos tan larga como la longitud que desea, calcule el número apropiado de repeticiones y colóquelo 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'
Luego, puede recortarlo a la longitud exacta que desee con un segmento de 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 la respuesta de pillmod de que probablemente nadie se desplaza lo suficiente como para notarlo, puede usar divmod
para calcular la cantidad de repeticiones completas necesarias y la cantidad de caracteres adicionales, todo a la vez:
def pillmod_repeat_to_length(s, wanted):
a, b = divmod(wanted, len(s))
return s * a + s[:b]
¿Cual es mejor? Vamos a compararlo:
>>> 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]
Entonces, la versión de pillmod es un 40% más lenta, lo cual es una lástima, ya que personalmente creo que es mucho más legible. Hay varias razones posibles para esto, comenzando con la compilación de aproximadamente un 40% más de instrucciones de código de bytes.
Nota: estos ejemplos usan el //
operador new-ish para truncar la división de enteros. Esto a menudo se llama una característica de Python 3, pero de acuerdo con PEP 238 , se introdujo en Python 2.2. Solo tiene que usarlo en Python 3 (o en módulos que lo tengan from __future__ import division
), pero puede usarlo independientemente.
//
en Python 3? O dejar caer+1
y usar una llamada explícita a una función de techo sería suficiente. Además, una nota: la cadena generada en realidad tiene una repetición adicional cuando se divide de manera uniforme; el empalme corta el extra. Eso me confundió al principio.