234

将字符串重复到一定长度的有效方法是什么?例如:repeat('abc', 7) -> 'abcabca'

这是我当前的代码:

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

有没有更好(更pythonic)的方法来做到这一点?也许使用列表理解?

4

14 回答 14

720

Jason Scheirer's answer is correct but could use some more exposition.

First off, to repeat a string an integer number of times, you can use overloaded multiplication:

>>> 'abc' * 7
'abcabcabcabcabcabcabc'

So, to repeat a string until it's at least as long as the length you want, you calculate the appropriate number of repeats and put it on the right-hand side of that multiplication operator:

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

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

Then, you can trim it to the exact length you want with an array slice:

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

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

Alternatively, as suggested in pillmod's answer that probably nobody scrolls down far enough to notice anymore, you can use divmod to compute the number of full repetitions needed, and the number of extra characters, all at once:

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

Which is better? Let's benchmark it:

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

So, pillmod's version is something like 40% slower, which is too bad, since personally I think it's much more readable. There are several possible reasons for this, starting with its compiling to about 40% more bytecode instructions.

Note: these examples use the new-ish // operator for truncating integer division. This is often called a Python 3 feature, but according to PEP 238, it was introduced all the way back in Python 2.2. You only have to use it in Python 3 (or in modules that have from __future__ import division) but you can use it regardless.

于 2010-08-02T19:30:44.530 回答
82
def repeat_to_length(string_to_expand, length):
   return (string_to_expand * ((length/len(string_to_expand))+1))[:length]

For python3:

def repeat_to_length(string_to_expand, length):
    return (string_to_expand * (int(length/len(string_to_expand))+1))[:length]
于 2010-08-02T19:30:35.960 回答
67

这是非常pythonic:

newstring = 'abc'*5
print newstring[0:6]
于 2013-11-12T16:45:49.977 回答
35
def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]
于 2010-08-02T19:50:43.163 回答
15
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))
于 2010-08-02T19:39:18.813 回答
7

也许不是最有效的解决方案,但肯定简短而简单:

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

repstr("foobar", 14)

给出“foobarfoobarfo”。关于这个版本的一件事是,如果 length < len(string) 则输出字符串将被截断。例如:

repstr("foobar", 3)

给出“foo”。

编辑:实际上令我惊讶的是,这比当前接受的解决方案('repeat_to_length' 函数)更快,至少在短字符串上:

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

据推测,如果字符串很长,或者长度非常高(也就是说,如果string * length部分的浪费很高),那么它的性能就会很差。实际上我们可以修改上面的内容来验证这一点:

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
于 2012-01-26T16:30:52.643 回答
6

How about string * (length / len(string)) + string[0:(length % len(string))]

于 2010-08-02T19:31:21.190 回答
6

我用这个:

def extend_string(s, l):
    return (s*l)[:l]
于 2013-09-12T11:11:06.733 回答
5

并不是说这个问题没有足够的答案,而是有一个重复功能;只需要列出一个列表然后加入输出:

from itertools import repeat

def rep(s,n):
  ''.join(list(repeat(s,n))
于 2012-09-20T05:58:59.647 回答
3

耶递归!

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

不会永远扩展,但它适用于较小的字符串。它很漂亮。

我承认我刚读过 Little Schemer,我现在喜欢递归。

于 2010-08-02T19:55:10.690 回答
1

这是使用列表推导的一种方法,尽管随着rpt字符串长度的增加它越来越浪费。

def repeat(rpt, length):
    return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
于 2010-08-02T19:35:52.240 回答
1

另一种 FP 方法:

def repeat_string(string_to_repeat, repetitions):
    return ''.join([ string_to_repeat for n in range(repetitions)])
于 2012-02-19T16:46:24.873 回答
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))
于 2019-01-01T17:06:08.857 回答
0
c = s.count('a')    
div=n//len(s)    
if n%len(s)==0:
    c= c*div
else:
    m = n%len(s)
    c = c*div+s[:m].count('a')
print(c)
于 2021-04-28T09:48:14.717 回答