Повторить строку до определенной длины
Что такое эффективный способ повторения строки до определенной длины? Например: 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
Есть ли лучший (более питонический) способ сделать это? Возможно, используя понимание списка?
Ответы
Ответ 1
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]
Ответ 2
Ответ Джейсона Шайрера верный, но мог бы использовать еще немного изложения.
Во-первых, чтобы повторить строку целое число раз, вы можете использовать перегруженное умножение:
>>> '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
), но вы можете использовать его независимо.
Ответ 3
Это довольно pythonic:
newstring = 'abc'*5
print newstring[0:6]
Ответ 4
def rep(s, m):
a, b = divmod(m, len(s))
return s * a + s[:b]
Ответ 5
from itertools import cycle, islice
def srepeat(string, n):
return ''.join(islice(cycle(string), n))
Ответ 6
Как насчет string * (length / len(string)) + string[0:(length % len(string))]
Ответ 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
Ответ 8
Не то, чтобы ответа на этот вопрос было недостаточно, но есть функция повторения; просто нужно составить список и затем присоединиться к выходу:
from itertools import repeat
def rep(s,n):
''.join(list(repeat(s,n))
Ответ 9
i использую это:
def extend_string(s, l):
return (s*l)[:l]
Ответ 10
Рекурсия Yay!
def trunc(s,l):
if l > 0:
return s[:l] + trunc(s, l - len(s))
return ''
Не будет масштабироваться вечно, но отлично подходит для небольших строк. И это довольно.
Я признаю, что я просто прочитал Little Schemer, и мне нравится рекурсия прямо сейчас.
Ответ 11
Это один из способов сделать это, используя понимание списка, хотя оно становится все более расточительным по мере увеличения длины строки rpt
.
def repeat(rpt, length):
return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
Ответ 12
Другой подход к FP:
def repeat_string(string_to_repeat, repetitions):
return ''.join([ string_to_repeat for n in range(repetitions)])
Ответ 13
import numpy as np
''.join(np.array(10 * ["string"]).tolist())
Ответ 14
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))