2010-08-02 9 views
130

Qu'est-ce qu'un moyen efficace de répéter une chaîne à une certaine longueur? Par exemple: repeat('abc', 7) -> 'abcabca'Répéter la chaîne jusqu'à une certaine longueur

Voici mon code actuel:

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

Y at-il une meilleure façon (plus de pythonique) pour le faire? Peut-être en utilisant la compréhension de la liste?

Répondre

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

Pour python3:

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

On dirait que c'est en profitant du nombre entier division. Cela ne doit-il pas être '//' dans Python 3? Ou abandonner le '+ 1' et utiliser un appel explicite à une fonction de plafond suffirait. Aussi, une note: la chaîne générée a en fait une répétition supplémentaire quand elle se divise uniformément; l'extra est coupé par l'épissure. Cela m'a troublé au début. – jpmc26

+0

'int()' fait la même chose ici, mais oui, '//' peut être microscopiquement plus rapide, parce qu'il fait la division et le plancher dans une commande au lieu de deux. – Doyousketch2

489

Répétition d'une chaîne plusieurs fois fixe est une opération intégrée:

'abc' * 7 

Ainsi, calculer simplement le nombre de répétitions que vous devez atteindre la longueur que vous voulez, et mettez cela sur le RHS. Vous devrez ensuite le couper à la bonne longueur.

(Il semble que ce soit ce que l'autre réponse fait, mais un peu plus d'explications semblait utile.)

+7

Ceci devrait être la réponse acceptée. –

+8

Non, OP souhaite que le résultat soit de longueur 7 (ce qui n'est pas un multiple de 3). – IanS

+0

Quel était le nom de cette fonctionnalité? Concat répété ??? –

4

Que diriez-vous string * (length/len(string)) + string[0:(length % len(string))]

+0

'length/len (string)' doit être encapsulé entre parenthèses, et il vous manque le dernier ']'. – MikeWyatt

+1

Le plus lisible/intuitive jusqu'à présent, à mon avis. Je pense que vous devez utiliser '//' pour la division entière en Python 3. Le '0' dans la splice est optionnel. (Le colon est nécessaire, bien sûr.) – jpmc26

1

C'est une façon de le faire en utilisant une compréhension de liste, bien que c'est de plus en plus gaspilleur à mesure que la longueur de la chaîne augmente.

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

certainement le plus beau à ce jour. +1 – Triptych

+0

Et cela fonctionne correctement sur les chaînes qui contiennent des valeurs numériques +1 – Ropstah

+2

Cela devrait être la réponse acceptée. – Nimrod

3

récursion Yay!

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

Est-ce pas pour toujours l'échelle, mais il est très bien pour les chaînes plus petites. Et c'est joli. J'avoue que je viens de lire le Petit Schemer et j'aime la récursivité en ce moment.

3

Peut-être pas la solution la plus efficace, mais certainement à court & simple:

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

repstr("foobar", 14) 

Donne "foobarfoobarfo". Une chose à propos de cette version est que si la longueur < len (chaîne) alors la chaîne de sortie sera tronquée. Par exemple:

repstr("foobar", 3) 

Donne "foo".

Edit: en fait à ma grande surprise, c'est plus rapide que la solution actuellement acceptée (la fonction « repeat_to_length »), au moins sur les chaînes courtes:

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 

On peut supposer que si la chaîne était longue, ou la longueur était très élevé (c'est-à-dire, si le gaspillage de la partie string * length était élevé) alors il aurait de mauvaises performances.Et en fait, nous pouvons modifier ce qui précède pour vérifier:

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

Vous pouvez ajouter un commutateur entre les deux versions en fonction des longueurs d'entrée et de sortie pour une optimisation maximale. –

0

Un autre aproche FP:

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

Non qu'il n'y a pas eu assez de réponses à cette question, mais il y a une fonction de répétition; juste besoin de faire une liste de puis rejoindre la sortie:

from itertools import repeat 

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

j'utilise ceci:

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

C'est assez pythonique:

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

'0: 7' si vous voulez 7 caractères comme OP. –

+0

Ceci devrait être marqué comme la bonne réponse. – marverix

Questions connexes