Wiederholen Sie die Zeichenfolge bis zu einer bestimmten Länge


204

Was ist ein effizienter Weg, um eine Zeichenfolge bis zu einer bestimmten Länge zu 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 Listenverständnis?

Antworten:


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

5
Sieht so aus, als würde dies die Ganzzahldivision ausnutzen. Muss das nicht //in Python 3 sein? Oder das Löschen +1und Verwenden eines expliziten Aufrufs einer Deckenfunktion würde ausreichen. Außerdem ein Hinweis: Die generierte Zeichenfolge hat tatsächlich eine zusätzliche Wiederholung, wenn sie gleichmäßig geteilt wird. Das Extra wird durch den Spleiß abgeschnitten. Das hat mich zuerst verwirrt.
jpmc26

int()macht hier das Gleiche, aber ja, //könnte mikroskopisch schneller sein, weil es die Teilung und den Boden in einem Befehl anstelle von zwei ausführt.
Doyousketch2

667

Die Antwort von Jason Scheirer ist richtig, könnte aber eine weitere Darstellung gebrauchen.

Um eine Zeichenfolge ganzzahlig zu wiederholen, können Sie zunächst die überladene Multiplikation verwenden:

>>> 'abc' * 7
'abcabcabcabcabcabcabc'

Um eine Zeichenfolge zu wiederholen, bis sie mindestens so lang ist wie die gewünschte Länge, berechnen Sie die entsprechende Anzahl von Wiederholungen und setzen sie auf die rechte Seite dieses Multiplikationsoperators:

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

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

Anschließend können Sie es mit einem Array-Slice auf die gewünschte Länge zuschneiden:

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

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

Alternativ können Sie, wie in der Antwort von pillmod vorgeschlagen , dass wahrscheinlich niemand mehr weit genug nach unten scrollt, um es zu bemerken, divmoddie Anzahl der erforderlichen vollständigen Wiederholungen und die Anzahl der zusätzlichen Zeichen gleichzeitig berechnen:

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

Welches ist besser? Lassen Sie es uns vergleichen:

>>> 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 Version von pillmod ist also ungefähr 40% langsamer, was schade ist, da ich persönlich denke, dass sie viel besser lesbar ist. Es gibt mehrere mögliche Gründe dafür, angefangen beim Kompilieren bis zu etwa 40% mehr Bytecode-Anweisungen.

Hinweis: In diesen Beispielen wird der //Operator new-ish zum Abschneiden der Ganzzahldivision verwendet. Dies wird oft als Python 3-Funktion bezeichnet, wurde jedoch laut PEP 238 bereits in Python 2.2 eingeführt. Sie müssen es nur in Python 3 (oder in Modulen mit from __future__ import division) verwenden, aber Sie können es trotzdem verwenden.


8
Nein, OP möchte, dass das Ergebnis die Länge 7 hat (was kein Vielfaches von 3 ist).
IanS

1
Ich bin ein bisschen in Konflikt geraten, weil dies nicht die richtige Antwort für OP ist, aber die richtige Antwort für mich und 489 andere Leute ...
Matt Fletcher

2
@ MattFletcher Sie haben mich gerade über die Linie von "Ich sollte dies als Erklärung der akzeptierten Antwort umschreiben " zu "Ich werde dies umschreiben ..."
geschoben ;-)



14
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))

Dies ist, was ich verwende, wenn ich nur über die Zeichenfolge iterieren muss (dann ist kein Join erforderlich). Lassen Sie die Python-Bibliotheken den Job machen.
wihlke

7

Vielleicht nicht die effizienteste Lösung, aber sicherlich kurz und einfach:

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

repstr("foobar", 14)

Gibt "foobarfoobarfo". Eine Sache bei dieser Version ist, dass wenn die Länge <len (Zeichenfolge) ist, die Ausgabezeichenfolge abgeschnitten wird. Beispielsweise:

repstr("foobar", 3)

Gibt "foo".

Bearbeiten: Eigentlich ist dies zu meiner Überraschung schneller als die derzeit akzeptierte Lösung (die Funktion 'repeat_to_length'), zumindest bei kurzen Zeichenfolgen:

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

Vermutlich würde die Saite string * lengthschlecht funktionieren, wenn sie lang oder sehr lang wäre (dh wenn die Verschwendung des Teils hoch wäre). Und tatsächlich können wir das oben Gesagte ändern, um dies zu überprüfen:

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
Sie können einen Wechsel zwischen den beiden Versionen basierend auf den Eingabe- und Ausgabelängen hinzufügen, um eine maximale Optimierung zu erzielen.
Mad Physicist

6

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


length / len(string)muss in Klammern eingeschlossen sein, und Sie vermissen den letzten ].
MikeWyatt

1
Das bisher lesbarste / intuitivste, meiner Meinung nach. Ich denke, Sie müssen //für die Ganzzahldivision in Python 3 verwenden. Das 0im Spleiß ist optional. (Der Doppelpunkt ist natürlich erforderlich.)
jpmc26


5

Nicht, dass es nicht genügend Antworten auf diese Frage gegeben hätte, aber es gibt eine Wiederholungsfunktion. Sie müssen nur eine Liste erstellen und dann die Ausgabe verbinden:

from itertools import repeat

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

Dies beantwortet die Frage nicht. Dieser wiederholt die Zeichenfolge X-mal, er wiederholt sie erst nach X-Länge. ZB "abc", 4würde erwarten "abca". Dies würde schaffenabcabcabcabc
Marcus Lind

3

Yay Rekursion!

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

Skaliert nicht für immer, ist aber für kleinere Saiten in Ordnung. Und es ist hübsch.

Ich gebe zu, ich habe gerade den kleinen Schemer gelesen und ich mag jetzt Rekursion.


1

Dies ist eine Möglichkeit, dies mithilfe eines Listenverständnisses zu tun, obwohl es mit zunehmender Länge der rptZeichenfolge zunehmend verschwenderisch wird .

def repeat(rpt, length):
    return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]

0

Ein weiterer FP-Ansatz:

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

0
def extended_string (word, length) :

    extra_long_word = word * (length//len(word) + 1)
    required_string = extra_long_word[:length]
    return required_string

print(extended_string("abc", 7))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.