Повторить строку до определенной длины
каков эффективный способ повторить строку до определенной длины? Например: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) способ сделать это? Может быть, используя понимание списка?
12 ответов:
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]
ответ Джейсона Шайрера правильный, но может использовать еще несколько экспозиций.
во-первых, чтобы повторить строку целое число раз, вы можете использовать перегруженное умножение:
>>> '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 это!--20--> что, вероятно, никто не прокручивает вниз достаточно далеко, чтобы заметить больше, вы можете использовать
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), но можете использовать его независимо от.
from itertools import cycle, islice def srepeat(string, n): return ''.join(islice(cycle(string), n))
возможно, не самое эффективное решение, но, конечно, коротко и просто:
def repstr(string, length): return (string * length)[0:length] repstr("foobar", 14)дает "foobarfoobarfo". Одна вещь об этой версии заключается в том, что если length
repstr("foobar", 3)дает "фу".
Edit: на самом деле, к моему удивлению, это быстрее, чем принятое в настоящее время решение (функция '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
Не то, чтобы не было достаточно ответов на этот вопрос, но есть функция повтора; просто нужно сделать список, а затем присоединиться к выходу:
from itertools import repeat def rep(s,n): ''.join(list(repeat(s,n))
Ура рекурсия!
def trunc(s,l): if l > 0: return s[:l] + trunc(s, l - len(s)) return ''не будет масштабироваться вечно, но это нормально для небольших строк. И это очень красиво.
Я признаю, что только что прочитал маленький интриган, и мне нравится рекурсия прямо сейчас.
Это один из способов сделать это, используя список понимания, хотя это более расточительно, как длина
rptстрока увеличивает.def repeat(rpt, length): return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
еще один FP aproach:
def repeat_string(string_to_repeat, repetitions): return ''.join([ string_to_repeat for n in range(repetitions)])
Comments