重复字符串一定长度


204

将字符串重复到一定长度的有效方法是什么?例如: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)来做到这一点?也许使用列表推导?

Answers:


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

5
看起来这是在利用整数除法。不需要//在Python 3中吗?或删除+1并使用对吊顶函数的显式调用就足够了。另外,请注意:生成的字符串在平均分配时实际上会有一个额外的重复。多余的部分被接头切断了。起初那使我感到困惑。
jpmc26 2013年

int()在这里做同样的事情,但是是的,//可能在微观上更快,因为它在一个命令而不是两个命令中进行除法和求和。
Doyousketch2

667

杰森·谢尼尔(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一直引入的。你只拥有在Python 3(或在具有模块使用它from __future__ import division),但你可以不考虑使用它。


8
不,OP希望结果​​的长度为7(不是3的倍数)。
IanS

1
我有点矛盾,因为这不是OP的正确答案,但对我和489个其他人来说是正确的答案……
Matt Fletcher

2
@MattFletcher您刚刚把我从“我应该重写它作为可接受的答案的解释者”到“我重写此...”的行上
推开


34
def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]

14
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))

这就是我只需要遍历字符串(然后不需要连接)时使用的方法。让python库完成这项工作。
wihlke

7

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

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

repstr("foobar", 14)

给出“ foobarfoobarfo”。关于此版本的一件事是,如果长度<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

1
您可以根据输入和输出长度在两个版本之间添加一个开关,以实现最大程度的优化。
疯狂物理学家,

6

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


length / len(string)需要用括号括起来,而您错过了last ]
MikeWyatt

1
在我看来,到目前为止最易读/最直观。我认为您需要//在Python 3中使用整数除法0。(当然必须使用冒号。)
jpmc26 2013年


5

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

from itertools import repeat

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

这不能回答问题。这个重复字符串X次,直到X长度才重复。如"abc", 4期望的"abca"。这将创建abcabcabcabc
Marcus Lind

3

耶递归!

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

不会永远缩放,但是对于较小的字符串来说很好。很漂亮

我承认我刚刚读了Little Schemer,并且现在喜欢递归。


1

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

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

0

另一个FP方法:

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

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))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.