2010-08-02 16 views
130

Wie kann eine Zeichenfolge auf eine bestimmte Länge effizient wiederholt werden? ZB: repeat('abc', 7) -> 'abcabca'Zeichenfolge auf bestimmte Länge wiederholen

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 (pythonic) Weg, dies zu tun? Vielleicht mit Listenverständnis?

Antwort

37
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

so aussieht wird ausgenutzt, Integer übernimmt Aufteilung. Muss das nicht "//" in Python 3 sein? Oder die "+ 1" fallen lassen und ein expliziter Aufruf einer Deckenfunktion wäre ausreichend. Auch eine Anmerkung: Die erzeugte Zeichenfolge hat tatsächlich eine zusätzliche Wiederholung, wenn sie sich gleichmäßig teilt; das Extra wird durch den Spleiß abgeschnitten. Das hat mich zuerst verwirrt. – jpmc26

+0

'int()' macht das gleiche hier, aber yea, '//' könnte mikroskopisch schneller sein, weil es die Division & Floor in einem Befehl statt in zwei durchführt. – Doyousketch2

489

eine Zeichenfolge eine feste Anzahl von Malen ist eine integrierte Bedienung:

'abc' * 7 

So berechnen nur die Anzahl der Wiederholungen Sie müssen erreiche die gewünschte Länge und lege das auf die RHS. Sie müssen es dann auf die richtige Länge trimmen. obwohl

(Es scheint, dass das ist, was die andere Antwort tut, aber ein bisschen mehr Erklärung schien nützlich.)

+7

Dies sollte die akzeptierte Antwort sein. –

+8

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

+0

Wie war der Name dieses Features? Wiederholte Concat ??? –

4

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

+0

'length/len (string)' muss ein Wrapper in Klammern sein und das letzte ']' fehlt. – MikeWyatt

+1

Die meisten lesbar/intuitiv bisher, meiner Meinung nach. Ich denke, Sie müssen '//' für die Integer-Division in Python 3 verwenden. Die '0' im Spleiß ist optional. (Der Doppelpunkt ist natürlich erforderlich.) – jpmc26

1

Dies ist eine Möglichkeit, es mit einer Liste Verständnis zu tun, es wird zunehmend verschwenderisch, wenn die Länge der rpt Zeichenfolge zunimmt.

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

auf jeden Fall der netteste bisher. +1 – Triptych

+0

Und es funktioniert ordnungsgemäß auf Zeichenfolgen, die numerische Werte enthalten +1 – Ropstah

+2

Dies sollte die akzeptierte Antwort sein. – Nimrod

3

Yay Rekursion!

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

Wird nicht immer maßstäblich, aber es ist für kleinere Strings in Ordnung. Und es ist hübsch.

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

3

Vielleicht nicht die effizienteste Lösung, aber sicherlich kurze & einfach:

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

repstr("foobar", 14) 

Gibt "foobarfoobarfo". Eine Sache über diese Version ist, dass bei Länge < len (string) dann die Ausgabezeichenfolge abgeschnitten wird. Zum Beispiel:

repstr("foobar", 3) 

Gibt "foo".

Edit: tatsächlich zu meiner Überraschung, das ist schneller als die derzeit akzeptierte Lösung (die ‚repeat_to_length‘ -Funktion), zumindest auf kurze Strings:

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 war lang, oder die Länge war sehr hoch (das heißt, wenn die Verschwendung des string * length Teils hoch war), dann würde es schlecht funktionieren.Und in der Tat können wir die oben ändern, 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 Schalter zwischen den beiden Versionen auf der Grundlage der Eingabe- und Ausgabedauer für maximale Optimierung hinzufügen. –

0

Ein weiterer FP aproach:

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

Nicht, dass es nicht genug gewesen, um Antworten auf diese Frage, aber es gibt eine Repeat-Funktion; müssen nur eine Liste und dann den Ausgang anschließen machen:

from itertools import repeat 

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

i verwenden:

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

Das ist ziemlich pythonic:

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

'0: 7' wenn du 7 Zeichen wie OP willst. –

+0

Dies sollte als die richtige Antwort markiert werden. – marverix

Verwandte Themen