2010-08-02 17 views
130

¿Cuál es una forma eficiente de repetir una cadena a una determinada longitud? Por ejemplo: repeat('abc', 7) -> 'abcabca'Repite cadena a cierta longitud

Aquí está 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 

¿Existe una (más Pythonic) forma mejor de hacer esto? Tal vez usando la lista de comprensión?

Respuesta

37
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] 
+5

Parece que esto está tomando ventaja de número entero división. ¿No necesita ser '//' en Python 3? O soltar el '+ 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 extra se corta por el empalme. Eso me confundió al principio. – jpmc26

+0

'int()' hace lo mismo aquí, pero sí, '//' podría ser microscópicamente más rápido, porque hace la división y la palabra en un comando en lugar de dos. – Doyousketch2

489

Repetición de una cadena de un número fijo de veces que es una operación integrada:

'abc' * 7 

lo tanto, sólo calcular el número de repeticiones que usted necesita alcance la longitud que desee, y ponga eso en el RHS. Luego deberá recortarla a la longitud correcta.

(Parece ser que esto es lo que hace la otra respuesta, pero un poco más de explicación pareció útil.)

+7

Esta debería ser la respuesta aceptada. –

+8

No, OP quiere que el resultado sea de longitud 7 (que no es un múltiplo de 3). – IanS

+0

¿Cuál era el nombre de esta característica? Repetido concat? –

4

¿Qué tal string * (length/len(string)) + string[0:(length % len(string))]

+0

'length/len (string)' necesita ser contenedor entre paréntesis, y le falta el último ']'. – MikeWyatt

+1

Lo más legible/intuitivo hasta ahora, en mi opinión. Creo que necesitas usar '//' para la división de enteros en Python 3. El '0' en el empalme es opcional. (Se requieren los dos puntos, por supuesto.) – jpmc26

1

Ésta es una manera de hacerlo usando una lista por comprensión, aunque es cada vez más derrochador a medida que aumenta la longitud de la cadena rpt.

def repeat(rpt, length): 
    return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length] 
13
from itertools import cycle, islice 
def srepeat(string, n): 
    return ''.join(islice(cycle(string), n)) 
29
def rep(s, m): 
    a, b = divmod(m, len(s)) 
    return s * a + s[:b] 
+1

definitivamente el mejor aspecto hasta ahora. +1 – Triptych

+0

Y funciona correctamente en cadenas que contienen valores numéricos +1 – Ropstah

+2

Esta debería ser la respuesta aceptada. – Nimrod

3

Yay recursividad!

def trunc(s,l): 
    if l > 0: 
     return s[:l] + trunc(s, l - len(s)) 
    return '' 

no se escala para siempre, pero está bien para las cadenas más pequeñas. Y es lindo

Admito que acabo de leer el Pequeño Schemer y me gusta la recursión en este momento.

3

Tal vez no sea la solución más eficiente, pero ciertamente corta & simple:

def repstr(string, length): 
    return (string * length)[0:length] 

repstr("foobar", 14) 

Da "foobarfoobarfo". Una cosa sobre esta versión es que si la longitud es < len (cadena), la cadena de salida se truncará. Por ejemplo:

repstr("foobar", 3) 

Da "foo".

Editar: en realidad, para mi sorpresa, esto es más rápido que la solución actualmente aceptado (la función 'repeat_to_length'), al menos en cadenas cortas:

from timeit import Timer 
t1 = Timer("repstr('foofoo', 30)", 'from __main__ import repstr') 
t2 = Timer("repeat_to_length('foofoo', 30)", 'from __main__ import repeat_to_length') 
t1.timeit() # gives ~0.35 secs 
t2.timeit() # gives ~0.43 secs 

Es de suponer que si la cadena era larga, o la longitud era muy alto (es decir, si el desperdicio de la pieza string * length fuera alto), no funcionaría bien.Y, de hecho, podemos modificar el anterior para comprobar esto:

from timeit import Timer 
t1 = Timer("repstr('foofoo' * 10, 3000)", 'from __main__ import repstr') 
t2 = Timer("repeat_to_length('foofoo' * 10, 3000)", 'from __main__ import repeat_to_length') 
t1.timeit() # gives ~18.85 secs 
t2.timeit() # gives ~1.13 secs 
+1

Puede agregar un interruptor entre las dos versiones según las longitudes de entrada y salida para optimizar al máximo. –

0

Otro aproach FP:

def repeat_string(string_to_repeat, repetitions): 
    return ''.join([ string_to_repeat for n in range(repetitions)]) 
5

No es que no han sido suficientes respuestas a esta pregunta, pero no es una función de repetición; sólo tiene que hacer una lista de y luego unirse a la salida:

from itertools import repeat 

def rep(s,n): 
    ''.join(list(repeat(s,n)) 
6

yo uso esto:

def extend_string(s, l): 
    return (s*l)[:l] 
41

Esto es bastante Pythonic:

newstring = 'abc'*5 
print newstring[0:6] 
+9

'0: 7' si quieres 7 caracteres como OP. –

+0

Esto debe marcarse como la respuesta correcta. – marverix

Cuestiones relacionadas