将字符串重复到一定长度的有效方法是什么?例: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

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


当前回答

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

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

其他回答

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

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

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

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

当前打印(f"{'abc'*7}")生成:

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

python3:

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

Jason Scheirer的答案是正确的,但需要更多的阐述。

首先,要将一个字符串重复整数次,你可以使用重载乘法:

>>> 'abc' * 7
'abcabcabcabcabcabcabc'

所以,为了重复一个字符串,直到它至少和你想要的长度一样长,你计算出适当的重复次数,并把它放在乘法运算符的右边:

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

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

然后,你可以用数组切片把它修剪成你想要的长度:

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

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

或者,正如在pillmod的回答中所建议的那样,可能没有人会再向下滚动到足够远的地方,你可以使用divmod来计算所需的完整重复的数量,以及额外的字符数量,一次全部:

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

哪个更好?让我们进行基准测试:

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

所以,pillmod的版本大约慢了40%,这太糟糕了,因为我个人认为它的可读性更高。这有几个可能的原因,首先是它多编译了大约40%的字节码指令。

注意:这些例子使用new-ish //运算符来截断整数除法。这通常被称为Python 3特性,但根据PEP 238,它是在Python 2.2中引入的。你只需要在python3中使用它(或在有__future__导入除法的模块中),但你可以无论如何使用它。