标签归档: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

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

What is an efficient way to repeat a string to a certain length? Eg: repeat('abc', 7) -> 'abcabca'

Here is my current code:

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

Is there a better (more pythonic) way to do this? Maybe using list comprehension?


回答 0

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

回答 1

杰森·谢尼尔(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),但你可以不考虑使用它。

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.


回答 2

这是相当Pythonic的:

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

This is pretty pythonic:

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

回答 3

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

回答 4

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

回答 5

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

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

Perhaps not the most efficient solution, but certainly short & simple:

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

repstr("foobar", 14)

Gives “foobarfoobarfo”. One thing about this version is that if length < len(string) then the output string will be truncated. For example:

repstr("foobar", 3)

Gives “foo”.

Edit: actually to my surprise, this is faster than the currently accepted solution (the ‘repeat_to_length’ function), at least on short strings:

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

Presumably if the string was long, or length was very high (that is, if the wastefulness of the string * length part was high) then it would perform poorly. And in fact we can modify the above to verify this:

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

回答 6

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

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


回答 7

我用这个:

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

i use this:

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

回答 8

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

from itertools import repeat

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

Not that there haven’t been enough answers to this question, but there is a repeat function; just need to make a list of and then join the output:

from itertools import repeat

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

回答 9

耶递归!

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

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

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

Yay recursion!

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

Won’t scale forever, but it’s fine for smaller strings. And it’s pretty.

I admit I just read the Little Schemer and I like recursion right now.


回答 10

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

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

This is one way to do it using a list comprehension, though it’s increasingly wasteful as the length of the rpt string increases.

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

回答 11

另一个FP方法:

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

Another FP aproach:

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

回答 12

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