重复字符串到一定长度

Joh*_*ard 185 python string repeat

将字符串重复到一定长度的有效方法是什么?例如: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
Run Code Online (Sandbox Code Playgroud)

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

zwo*_*wol 631

Jason Scheirer的回答是正确的,但可以使用更多的说明.

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

>>> 'abc' * 7
'abcabcabcabcabcabcabc'
Run Code Online (Sandbox Code Playgroud)

因此,要重复一个字符串,直到它至少与您想要的长度一样长,您计算适当的重复次数并将其放在该乘法运算符的右侧:

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

>>> repeat_to_at_least_length('abc', 7)
'abcabcabc'
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用数组切片将其修剪为所需的精确长度:

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

>>> repeat_to_length('abc', 7)
'abcabca'
Run Code Online (Sandbox Code Playgroud)

或者,正如在pillmod的回答中所建议的那样,可能没有人向下滚动到足以让人注意,你可以divmod用来计算所需的完整重复次数和额外字符的数量,这些都是一次性的:

def pillmod_repeat_to_length(s, wanted):
    a, b = divmod(wanted, len(s))
    return s * a + s[:b]
Run Code Online (Sandbox Code Playgroud)

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

>>> 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]
Run Code Online (Sandbox Code Playgroud)

因此,pillmod的版本速度慢了40%,这太糟糕了,因为我个人觉得它更具可读性.这有几个可能的原因,从编译到大约40%的字节码指令开始.

注意:这些示例使用new-ish //运算符截断整数除法.这通常被称为 Python 3功能,但根据PEP 238,它在Python 2.2中一直被引入.您只需要在Python 3(或具有的模块from __future__ import division)使用它,但无论如何都可以使用它.

  • 不,OP希望结果​​长度为7(不是3的倍数). (8认同)
  • @MattFletcher你刚刚把我推到了"我应该把它重写为接受答案的解释器"到"我_will_重写这个......";-) (2认同)

小智 65

def repeat_to_length(string_to_expand, length):
   return (string_to_expand * ((length/len(string_to_expand))+1))[:length]
Run Code Online (Sandbox Code Playgroud)

对于python3:

def repeat_to_length(string_to_expand, length):
    return (string_to_expand * (int(length/len(string_to_expand))+1))[:length]
Run Code Online (Sandbox Code Playgroud)

  • 看起来这是利用整数除法.在Python 3中不需要`//`吗?或者删除`+ 1`并使用显式调用天花板功能就足够了.另外,注意:生成的字符串在均匀分割时实际上有一个额外的重复; 额外的东西被拼接切断了.起初这让我很困惑. (5认同)

小智 54

这是非常pythonic:

newstring = 'abc'*5
print newstring[0:6]
Run Code Online (Sandbox Code Playgroud)

  • `0:7`如果你想要像OP这样的7个字符. (12认同)

pil*_*her 32

def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]
Run Code Online (Sandbox Code Playgroud)


ken*_*ytm 14

from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))
Run Code Online (Sandbox Code Playgroud)


mur*_*d99 6

怎么样 string * (length / len(string)) + string[0:(length % len(string))]


Ada*_*kin 6

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

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

repstr("foobar", 14)
Run Code Online (Sandbox Code Playgroud)

给予"foobarfoobarfo".关于这个版本的一件事是,如果长度<len(字符串),那么输出字符串将被截断.例如:

repstr("foobar", 3)
Run Code Online (Sandbox Code Playgroud)

给"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
Run Code Online (Sandbox Code Playgroud)

据推测,如果琴弦很长,或者长度非常高(也就是说,如果部件的浪费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
Run Code Online (Sandbox Code Playgroud)


김민준*_*김민준 6

我用这个:

def extend_string(s, l):
    return (s*l)[:l]
Run Code Online (Sandbox Code Playgroud)


小智 5

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

from itertools import repeat

def rep(s,n):
  ''.join(list(repeat(s,n))
Run Code Online (Sandbox Code Playgroud)