Что эффективный путь состоит в том, чтобы повторить строку к определенной длине? Например: 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) способ сделать это? Возможно, с помощью понимания списка?
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 rep(s, m):
a, b = divmod(m, len(s))
return s * a + s[:b]
Ответ Джейсона Шейрера правильный, но можно было бы использовать еще кое-что.
Во-первых, чтобы повторить строку целое число раз, вы можете использовать перегруженное умножение:
>>> '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 (или в модулях, которые имеют из __future__ import Division
), но вы можете использовать его независимо.
Как насчет строка * (длина / длина (строка)) + строка [0: (длина% len (строка))]
from itertools import cycle, islice
def srepeat(string, n):
return ''.join(islice(cycle(string), n))
Ура, рекурсия!
def trunc(s,l):
if l > 0:
return s[:l] + trunc(s, l - len(s))
return ''
Не масштабируется вечно, но подходит для струн меньшего размера. И это красиво.
Признаюсь, я только что прочитал Little Schemer и сейчас мне нравится рекурсия.
Это один из способов сделать это с помощью понимания списка, хотя он становится все более расточительным по мере увеличения длины строки rpt
.
def repeat(rpt, length):
return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]