Повторите строку к определенной длине

Что эффективный путь состоит в том, чтобы повторить строку к определенной длине? Например: 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) способ сделать это? Возможно, с помощью понимания списка?

185
задан John Howard 2 August 2010 в 08:35
поделиться

7 ответов

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]
65
ответ дан 23 November 2019 в 05:50
поделиться
def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]
32
ответ дан 23 November 2019 в 05:50
поделиться

Ответ Джейсона Шейрера правильный, но можно было бы использовать еще кое-что.

Во-первых, чтобы повторить строку целое число раз, вы можете использовать перегруженное умножение:

>>> '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 ), но вы можете использовать его независимо.

631
ответ дан 23 November 2019 в 05:50
поделиться

Как насчет строка * (длина / длина (строка)) + строка [0: (длина% len (строка))]

6
ответ дан 23 November 2019 в 05:50
поделиться
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))
14
ответ дан 23 November 2019 в 05:50
поделиться

Ура, рекурсия!

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

Не масштабируется вечно, но подходит для струн меньшего размера. И это красиво.

Признаюсь, я только что прочитал Little Schemer и сейчас мне нравится рекурсия.

3
ответ дан 23 November 2019 в 05:50
поделиться

Это один из способов сделать это с помощью понимания списка, хотя он становится все более расточительным по мере увеличения длины строки rpt.

def repeat(rpt, length):
    return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
1
ответ дан 23 November 2019 в 05:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: