webentwicklung-frage-antwort-db.com.de

Wiederholen Sie die Zeichenfolge auf eine bestimmte Länge

Was ist eine effiziente Möglichkeit, eine Zeichenfolge bis zu einer bestimmten Länge zu wiederholen? ZB: 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 eine bessere (pythonischere) Möglichkeit, dies zu tun? Vielleicht mit Listenverständnis?

177
John Howard
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]
62
Jason Scheirer

Jason Scheirers Antwort ist richtig, könnte aber noch eine Erklärung gebrauchen.

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

>>> 'abc' * 7
'abcabcabcabcabcabcabc'

Um also eine Zeichenfolge zu wiederholen, bis sie mindestens so lang ist, wie Sie möchten, berechnen Sie die entsprechende Anzahl von Wiederholungen und setzen Sie sie rechts. 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, wie in pillmods Antwort vorgeschlagen, dass wahrscheinlich niemand weit genug nach unten scrollen kann, um es zu bemerken, können Sie divmod verwenden, um die Anzahl der erforderlichen vollständigen Wiederholungen zu berechnen. und die Anzahl der zusätzlichen Zeichen auf einmal:

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 40% mehr Bytecode-Anweisungen.

Hinweis: In diesen Beispielen wird der Operator new-ish // Zum Abschneiden der Ganzzahldivision verwendet. Dies wird oft als ein Python 3 -Feature bezeichnet, aber laut PEP 238 ist es wurde den ganzen Weg zurück in Python 2.2. Sie haben nur , um es in Python 3 (oder in Modulen mit from __future__ import division), Aber Sie können es trotzdem verwenden.

614
zwol

Das ist ziemlich Pythonic:

newstring = 'abc'*5
print newstring[0:6]
53
Helen K
def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]
32
pillmuncher
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))
14
kennytm

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 an dieser Version ist, dass wenn length <len (string) ist, der Ausgabe-String abgeschnitten wird. Zum Beispiel:

repstr("foobar", 3)

Gibt "foo".

Bearbeiten: Eigentlich ist dies zu meiner Überraschung schneller als die derzeit akzeptierte Lösung (die 'repeat_to_length'-Funktion), 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, wenn die Zeichenfolge lang oder sehr lang war (dh, wenn die Verschwendung des string * length Teil war hoch) dann würde es schlecht abschneiden. Tatsächlich können wir die obigen Änderungen vornehmen, 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
6
Adam Parkin

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

6
murgatroid99

ich benutze das:

def extend_string(s, l):
    return (s*l)[:l]
6
김민준

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

from itertools import repeat

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

Yay Rekursion!

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

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

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

3
Triptych

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

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

Ein weiterer FP Ansatz:

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