@steven-rumbalskiによって言及された裸の置換は、これを達成するための最も効率的な方法になりますが、それが唯一の方法ではありません。
リスト内包表記を使用した別のソリューションを次に示します。テキストがすでに行のリストに分割されている場合、これは を実行するよりもはるかに高速ですjoin()
。replace()
splitlines()
text = """A very very very very very very very very very very very very very very very very
long mutiline
string"""
lines = text.splitlines()
indented = [' ' + l for l in lines]
indented[0] = lines[0]
indented = '\n'.join(indented)
リストはその場で変更できますが、2 番目の変数を使用する場合と比較して、パフォーマンスが大幅に低下します。また、すべての行をインデントしてから、別の操作で最初の行を入れ替える方がやや高速です。
モジュールもありtextwrap
ます。インデントに textwrap を使用することは非 Pythonic であることに同意しません。行が改行を含む単一の文字列に結合されている場合、その文字列は本質的に折り返されます。インデントはテキスト ラッピングの論理的な拡張であるため、textwrap は私にとって理にかなっています。
遅いことを除けば。本当に、本当に遅いです。15倍遅いように。
Python 3 が追加さindent
れ、textwrap
再ラップなしのインデントが非常に簡単になりました。確かに、ラムダ述語を処理するよりエレガントな方法がありますが、これは元の質問が求めていたものとまったく同じです。
indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )
ここではtimeit
、さまざまな方法のいくつかの結果を示します。
>>> timeit.timeit(r"text.replace('\n', '\n ')", setup='text = """%s"""' % text)
0.5123521030182019
2 つのリスト内包表記ソリューション:
>>> timeit.timeit(r"indented = [' ' + i for i in lines]; indented[0] = lines[0]", setup='lines = """%s""".splitlines()' % text)
0.7037646849639714
>>> timeit.timeit(r"indented = [lines[0]] + [' ' + i for i in lines[1:]]", setup='lines = """%s""".splitlines()' % text)
1.0310905870283023
そして、残念なtextwrap
結果は次のとおりです。
>>> timeit.timeit(r"textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )", setup='import textwrap; text = """%s"""' % text)
7.7950868209591135
その時間の一部は恐ろしく非効率な述語である可能性があると思いましたが、それを削除しても、textwrap.indent
そのままの置換よりも 8 倍以上遅くなります。
>>> timeit.timeit(r"textwrap.indent(text, ' ')", setup='import textwrap; text = """%s"""' % text)
4.266149697010405