Nagie zastąpić wspomniane przez @steven-rumbalski będzie najskuteczniejszym sposobem do osiągnięcia tego celu, ale nie jest to jedyny sposób.
Oto kolejne rozwiązanie wykorzystujące wyliczenia list. Jeśli tekst został już podzielony na liście linii, będzie to znacznie szybciej niż bieganie join()
, replace()
i 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)
lista może być modyfikowana w miejscu, ale jest znaczącym kosztem wydajności w porównaniu z wykorzystaniem drugiego zmienna. Jest także umiarkowanie szybsze wcięcie wszystkich linii, a następnie zamiana pierwszego wiersza w innej operacji.
Istnieje również moduł textwrap
. Nie zgadzam się z tym, że używanie textwrap do wcięcia jest niepythoniczne. Jeśli linie są połączone w jeden ciąg zawierający znaki nowej linii, ten ciąg jest z natury zawijany. Wcięcie jest logicznym przedłużeniem zawijania tekstu, więc tekst jest dla mnie sensowny.
Z tym że jest wolny. Naprawdę, naprawdę wolno. Jak 15 razy wolniej.
Python 3 dodano indent
do textwrap
, co sprawia, że wcięcia bez ponownego owijania są bardzo łatwe. Z pewnością jest bardziej elegancki sposób obsługi orzeczenia lambda, ale robi to dokładnie to, o co prosiło pierwotne pytanie.
indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x)
Oto kilka timeit
wyniki różnych metod.
>>> timeit.timeit(r"text.replace('\n', '\n ')", setup='text = """%s"""' % text)
0.5123521030182019
dwóch list rozwiązań ze zrozumieniem:
>>> 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
i tu jest niefortunne textwrap
wynik:
>>> timeit.timeit(r"textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x)", setup='import textwrap; text = """%s"""' % text)
7.7950868209591135
Myślałem trochę tego czasu może być strasznie nieskuteczny orzecznik, ale nawet z usunięty, jest nadal ponad 8 razy wolniejszy niż samodzielny zamiennik.
>>> timeit.timeit(r"textwrap.indent(text, ' ')", setup='import textwrap; text = """%s"""' % text)
4.266149697010405
Z dokumentów dla 'previous_indent':" Łańcuch, który zostanie dodany do wszystkich wierszy zawijanych danych wyjściowych. " Ponieważ nic nie jest pakowane, nic nie jest wcięte. –