Zeichenfolge bis zu einer bestimmten Länge wiederholen

Wie lässt sich eine Zeichenkette bis zu einer bestimmten Länge effizient wiederholen? Z.B.: repeat('abc', 7) -> 'abcabca'

Hier ist mein aktueller Code:

def repeat(string, length):
    cur, old = 1, string
    while len(string) < length:
        string += old[cur-1]
        cur = (cur+1)%len(old)
    return string

Gibt es einen besseren (pythonischeren) Weg, dies zu tun? Vielleicht mit List Comprehension?

Die Antwort von Jason Scheirer'ist richtig, könnte aber noch etwas ausführlicher sein.

Zunächst einmal, um eine Zeichenfolge eine ganze Zahl von Zeiten zu wiederholen, können Sie überladen Multiplikation verwenden:

>>> 'abc' * 7
'abcabcabcabcabcabcabc'

Um also eine Zeichenkette zu wiederholen, bis sie mindestens so lang ist wie die gewünschte Länge, berechnet man die entsprechende Anzahl von Wiederholungen und setzt sie auf die rechte Seite des Multiplikationsoperators:

def repeat_to_at_least_length(s, wanted):
    return s * (wanted//len(s) + 1)

>>> repeat_to_at_least_length('abc', 7)
'abcabcabc'

Dann können Sie sie mit einem Array-Slice auf die gewünschte Länge kürzen:

def repeat_to_length(s, wanted):
    return (s * (wanted//len(s) + 1))[:wanted]

>>> repeat_to_length('abc', 7)
'abcabca'

Alternativ, wie in pillmod's Antwort vorgeschlagen, die wahrscheinlich niemand mehr weit genug nach unten scrollt, um sie zu bemerken, können Sie divmod verwenden, um die Anzahl der benötigten vollständigen Wiederholungen und die Anzahl der zusätzlichen Zeichen auf einmal zu berechnen:

def pillmod_repeat_to_length(s, wanted):
    a, b = divmod(wanted, len(s))
    return s * a + s[:b]

Was ist besser? Machen wir einen Vergleich:

>>> 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]

Die pillmod'-Version ist also etwa 40% langsamer, was schade ist, da ich persönlich denke, dass sie viel lesbarer ist. Dafür gibt es mehrere mögliche Gründe, angefangen bei der Kompilierung von etwa 40% mehr Bytecode-Anweisungen.

Hinweis: Diese Beispiele verwenden den neuartigen //-Operator zum Abschneiden von Integer-Divisionen. Dies wird oft als Python 3-Feature bezeichnet, aber laut PEP 238 wurde es bereits in Python 2.2 eingeführt. Man muss ihn nur in Python 3 verwenden (oder in Modulen, die from __future__ import division haben), aber man kann ihn trotzdem verwenden.

Kommentare (4)
Lösung
def repeat_to_length(string_to_expand, length):
   return (string_to_expand * ((length/len(string_to_expand))+1))[:length]

Für python3:

def repeat_to_length(string_to_expand, length):
    return (string_to_expand * (int(length/len(string_to_expand))+1))[:length]
Kommentare (2)

Wie wäre es mit string * (length / len(string)) + string[0:(length % len(string))]

Kommentare (2)