Memformat string output, perataan kanan

149

Saya sedang memproses file teks yang berisi koordinat x, y, z

     1      128  1298039
123388        0        2
....

setiap baris dibatasi menjadi 3 item menggunakan

words = line.split()

Setelah mengolah data, saya perlu menulis kembali koordinat dalam file txt lain sehingga item di setiap kolom disejajarkan dengan benar (serta file input). Setiap baris terdiri dari koordinat

line_new = words[0]  + '  ' + words[1]  + '  ' words[2].

Apakah ada manipulator seperti std::setw()dll di C ++ yang memungkinkan untuk mengatur lebar dan perataan?

justik
sumber

Jawaban:

230

Coba pendekatan ini menggunakan str.formatsintaks yang lebih baru :

line_new = '{:>12}  {:>12}  {:>12}'.format(word[0], word[1], word[2])

Dan inilah cara melakukannya menggunakan %sintaks lama (berguna untuk Python versi lama yang tidak mendukung str.format):

line_new = '%12s  %12s  %12s' % (word[0], word[1], word[2])
Mark Byers
sumber
39
Perhatikan bagaimana sintaks "lama" lebih bersih, lebih mudah dibaca, dan lebih pendek.
fyngyrz
2
Saya pikir saya akan menambahkan tautan yang lebih langsung daripada yang disediakan: docs.python.org/2/library/…
brw59
48
Singkatnya, saya tidak tahu apa arti sebenarnya dari pembersih, tetapi 'lebih mudah dibaca' hanya karena itu sudah umum, saya pikir. Jika Anda belum terbiasa dengan salah satu dari mereka, format baru tampaknya lebih mudah dibaca. ".format" untuk pemformatan string tentu tampak lebih intuitif daripada persentase / modulo. Panah kanan untuk perataan kanan juga tampak intuitif.
Tandai
2
@ Mark Salah satu cara cara lama lebih bersih adalah menggunakan lebih sedikit karakter. Ya dengan keakraban cara baru menjadi intuitif tetapi tidak bersih dan sederhana. Cara lama lebih intuitif bagi mereka yang terbiasa dengan sintaksis yang datang kepada kita melalui bahasa C terhormat, bahasa ketelitian dan ketelitian yang patut dicontoh. Apa preseden yang ada untuk cara baru?
Stephen Boston
2
@StephenBoston Saya akan meninggalkan keterbacaan untuk para ahli, tetapi cara baru ini benar-benar bersih. Orang tua tidak lagi opsional. % dapat dikacaukan dengan operator matematika (meskipun, tidak mungkin dalam konteks, tetapi sekilas yakin). Cara lama akan gagal jika kata [n] bukan tipe yang diharapkan (string dalam hal ini). Cara baru tidak perlu tahu apa tipe yang masuk, selalu bekerja. Bersih dan sederhana. Agar adil, saya tidak pernah merasa nyaman dengan gaya printf (saya kebanyakan melakukan C dengan cout).
Zim
53

Itu dapat dicapai dengan menggunakan rjust:

line_new = word[0].rjust(10) + word[1].rjust(10) + word[2].rjust(10)
Clwen
sumber
52

Anda dapat menyelaraskannya seperti itu:

print('{:>8} {:>8} {:>8}'.format(*words))

mana >berarti " menyelaraskan ke kanan " dan 8adalah lebar untuk nilai tertentu.

Dan inilah buktinya:

>>> for line in [[1, 128, 1298039], [123388, 0, 2]]:
    print('{:>8} {:>8} {:>8}'.format(*line))


       1      128  1298039
  123388        0        2

Ps. *lineberarti linedaftar akan dibongkar, jadi .format(*line)berfungsi sama dengan .format(line[0], line[1], line[2])(anggap lineadalah daftar dengan hanya tiga elemen).

Tadeck
sumber
27

Saya sangat menikmati interpolasi string literal baru di Python 3.6+:

line_new = f'{word[0]:>12}  {word[1]:>12}  {word[2]:>12}'

Referensi: PEP 498 - Interpolasi String Literal

dmitry_romanov
sumber
19

Berikut ini cara lain cara memformat menggunakan format 'f-string':

print(
    f"{'Trades:':<15}{cnt:>10}",
    f"\n{'Wins:':<15}{wins:>10}",
    f"\n{'Losses:':<15}{losses:>10}",
    f"\n{'Breakeven:':<15}{evens:>10}",
    f"\n{'Win/Loss Ratio:':<15}{win_r:>10}",
    f"\n{'Mean Win:':<15}{mean_w:>10}",
    f"\n{'Mean Loss:':<15}{mean_l:>10}",
    f"\n{'Mean:':<15}{mean_trd:>10}",
    f"\n{'Std Dev:':<15}{sd:>10}",
    f"\n{'Max Loss:':<15}{max_l:>10}",
    f"\n{'Max Win:':<15}{max_w:>10}",
    f"\n{'Sharpe Ratio:':<15}{sharpe_r:>10}",
)

Ini akan memberikan output sebagai berikut:

Trades:              2304
Wins:                1232
Losses:              1035
Breakeven:             37
Win/Loss Ratio:      1.19
Mean Win:           0.381
Mean Loss:         -0.395
Mean:               0.026
Std Dev:             0.56
Max Loss:          -3.406
Max Win:             4.09
Sharpe Ratio:      0.7395

Apa yang Anda lakukan di sini adalah Anda mengatakan bahwa kolom pertama panjangnya 15 karakter dan dibenarkan kiri dan kolom kedua (nilai) panjangnya 10 karakter dan itu dibenarkan benar.

Vlad Bezden
sumber
Apakah ada cara untuk menentukan lebar format? Dalam contoh ini jika Anda memutuskan untuk mengubah pemformatan menjadi 20 dan 15 lebar itu diperlukan untuk mengubah beberapa baris. widths = [15, 10] f"{'Trades:':<width[0]}{cnt:>width[1]}",Saya ingin mencapai sth seperti di atas.
Tomasz Sabała
1
Mengerti! Mungkin seseorang akan merasa terbantu. Saya perlu satu kurung bersarang lagi untuk ini:f"{'Trades:':<{width[0]}}{cnt:>{width[1]}}"
Tomasz Sabała
1
Terkadang jawaban terbaik adalah yang tidak menjawab pertanyaan yang tepat. Terima kasih untuk ini! :)
Brian Wiley
5

Tabulasi sederhana dari output:

a = 0.3333333
b = 200/3
print("variable a    variable b")
print("%10.2f    %10.2f" % (a, b))

keluaran:

variable a    variable b
      0.33         66.67

% 10.2f: 10 adalah panjang minimum dan 2 adalah jumlah tempat desimal.

Thoran
sumber
1

Untuk melakukannya dengan menggunakan f-string dan dengan kontrol jumlah digit tambahan:

print(f'A number -> {my_number:>20.5f}')
Belajar itu berantakan
sumber