문자열을 특정 길이로 반복


204

문자열을 특정 길이로 반복하는 효율적인 방법은 무엇입니까? 예 :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) 방법이 있습니까? 아마도 목록 이해력을 사용합니까?

답변:


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

5
정수 나누기를 이용하는 것 같습니다. //파이썬 3에 필요하지 않습니까? 또는 +1실링 함수에 대한 명시 적 호출을 삭제 하고 사용하면 충분합니다. 또한 참고 : 생성 된 문자열은 실제로 균등하게 나눌 때 추가 반복이 있습니다. 여분은 스플 라이스에 의해 차단됩니다. 처음에는 저를 혼란스럽게했습니다.
jpmc26

int()여기에서 똑같은 일을하지만 실제로 //두 개가 아닌 하나의 명령으로 나누기 및 바닥을 수행하기 때문에 현미경으로 더 빠를 수 있습니다.
Doyousketch2

667

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]

필필의 버전은 40 % 느리다. 개인적으로는 훨씬 더 읽기 쉽다고 생각하기 때문에 너무 나쁘다. 약 40 % 더 많은 바이트 코드 명령어로 컴파일하는 것으로 시작하는 몇 가지 이유가 있습니다.

참고 :이 예에서는 //정수 나누기를 자르기 위해 new-ish 연산자를 사용합니다 . 이것을 종종 Python 3 기능 이라고 하지만 PEP 238 에 따르면 Python 2.2에서 다시 도입되었습니다. 당신은 파이썬 3 (또는이 모듈에서 사용하는 from __future__ import division)하지만 당신은 에 관계없이 그것을 사용할 수 있습니다.


8
아니요, OP는 결과의 길이가 7 (3의 배수가 아님)이되기를 원합니다.
IanS

1
이것은 OP에 대한 정답은 아니지만 저와 489 명의 다른 사람들에게 정답이므로 약간 충돌합니다 ...
Matt Fletcher

2
@MattFletcher 당신은 "나는 이것을 받아 들일 것입니다 ...";-)
zwol



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

이것은 문자열을 반복해야 할 때 사용합니다 (그런 다음 조인이 필요하지 않습니다). 파이썬 라이브러리가 작업을 수행하도록하십시오.
wihlke

7

아마도 가장 효율적인 솔루션은 아니지만 짧고 간단합니다.

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

repstr("foobar", 14)

"foobarfoobarfo"를 제공합니다. 이 버전에 대한 한 가지는 length <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

1
최대 최적화를 위해 입력 및 출력 길이에 따라 두 버전 사이에 스위치를 추가 할 수 있습니다.
Mad Physicist 2016 년

6

어때요? string * (length / len(string)) + string[0:(length % len(string))]


length / len(string)괄호 안에 래퍼가 있어야하며 마지막이 누락되었습니다 ].
MikeWyatt

1
내 의견으로는 지금까지 가장 읽기 쉽고 직관적입니다. //파이썬 3에서 정수 나누기에 사용해야한다고 생각합니다 0. (콜론은 물론, 필요합니다.)
jpmc26

6

나는 이것을 사용한다 :

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

5

이 질문에 대한 답변이 충분하지 않았지만 반복 기능이 있습니다. 목록을 만든 다음 출력을 조인하면됩니다.

from itertools import repeat

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

이것은 질문에 대답하지 않습니다. 이것은 문자열 X를 반복하고 X 길이까지 반복하지 않습니다. 예를 "abc", 4기대 "abca". 이것은 만들 것abcabcabcabc
마커스 린드에게

3

예이 재귀!

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

영원히 확장되지는 않지만 작은 줄에는 좋습니다. 그리고 예쁘다.

나는 Little Schemer를 읽는 것을 인정하고 지금 재귀를 좋아합니다.


1

이것은리스트 이해를 사용하는 방법 중 하나이지만 줄 길이가 길어질수록 점점 더 낭비됩니다 rpt.

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

0

다른 FP aproach :

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

0
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))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.