234

文字列を特定の長さまで繰り返す効率的な方法は何ですか?例えば: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な)方法はありますか?たぶんリスト内包表記を使用していますか?

4

14 に答える 14

720

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]

つまり、pillmodのバージョンは40%遅いようなものですが、個人的にははるかに読みやすいと思うので、これは残念です。これにはいくつかの理由が考えられます。まず、約40%多くのバイトコード命令をコンパイルすることから始めます。

注:これらの例では、//整数除算を切り捨てるためにnew-ish演算子を使用しています。これはPython3機能と呼ばれることがよくありますが、 PEP 238によると、 Python2.2でずっと前に導入されました。Python 3(またはを含むモジュール)でのみ使用する必要がありますが、関係なく使用できます。from __future__ import division

于 2010-08-02T19:30:44.530 に答える
82
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]
于 2010-08-02T19:30:35.960 に答える
67

これはかなりpythonicです:

newstring = 'abc'*5
print newstring[0:6]
于 2013-11-12T16:45:49.977 に答える
35
def rep(s, m):
    a, b = divmod(m, len(s))
    return s * a + s[:b]
于 2010-08-02T19:50:43.163 に答える
15
from itertools import cycle, islice
def srepeat(string, n):
   return ''.join(islice(cycle(string), n))
于 2010-08-02T19:39:18.813 に答える
7

おそらく最も効率的な解決策ではありませんが、確かに短くて単純です。

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

repstr("foobar", 14)

「foobarfoobarfo」を与えます。このバージョンの1つは、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
于 2012-01-26T16:30:52.643 に答える
6

どうですかstring * (length / len(string)) + string[0:(length % len(string))]

于 2010-08-02T19:31:21.190 に答える
6

私はこれを使用します:

def extend_string(s, l):
    return (s*l)[:l]
于 2013-09-12T11:11:06.733 に答える
5

この質問に対する十分な回答がなかったわけではありませんが、繰り返し機能があります。リストを作成してから、出力に参加する必要があります。

from itertools import repeat

def rep(s,n):
  ''.join(list(repeat(s,n))
于 2012-09-20T05:58:59.647 に答える
3

イェーイ再帰!

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

永久にスケーリングすることはありませんが、小さい文字列には問題ありません。そして、それはきれいです。

私はLittleSchemerを読んだばかりで、今は再帰が好きだと認めています。

于 2010-08-02T19:55:10.690 に答える
1

rptこれはリスト内包表記を使用して行う1つの方法ですが、文字列の長さが長くなるにつれて無駄が増えます。

def repeat(rpt, length):
    return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
于 2010-08-02T19:35:52.240 に答える
1

別のFPアプローチ:

def repeat_string(string_to_repeat, repetitions):
    return ''.join([ string_to_repeat for n in range(repetitions)])
于 2012-02-19T16:46:24.873 に答える
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))
于 2019-01-01T17:06:08.857 に答える
0
c = s.count('a')    
div=n//len(s)    
if n%len(s)==0:
    c= c*div
else:
    m = n%len(s)
    c = c*div+s[:m].count('a')
print(c)
于 2021-04-28T09:48:14.717 に答える