Formater la chaîne de sortie, alignement à droite

149

Je traite un fichier texte contenant les coordonnées x, y, z

     1      128  1298039
123388        0        2
....

chaque ligne est délimitée en 3 éléments en utilisant

words = line.split()

Après le traitement des données, je dois réécrire les coordonnées dans un autre fichier txt afin que les éléments de chaque colonne soient alignés à droite (ainsi que le fichier d'entrée). Chaque ligne est composée des coordonnées

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

Existe-t-il un manipulateur comme std::setw()etc. en C ++ permettant de définir la largeur et l'alignement?

justik
la source

Réponses:

230

Essayez cette approche en utilisant la nouvelle str.formatsyntaxe :

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

Et voici comment le faire en utilisant l'ancienne %syntaxe (utile pour les anciennes versions de Python qui ne prennent pas en charge str.format):

line_new = '%12s  %12s  %12s' % (word[0], word[1], word[2])
Mark Byers
la source
39
Notez comment la «vieille» syntaxe est plus propre, plus facile à lire et plus courte.
fyngyrz
2
J'ai pensé ajouter un lien plus direct que celui fourni: docs.python.org/2/library/…
brw59
48
Plus court, bien sûr, je ne sais pas ce que signifie vraiment nettoyant, mais «plus facile à lire» est simplement parce que c'est familier, je pense. Si vous ne connaissez pas déjà l'un d'entre eux, le nouveau format semble plus facile à lire. ".format" pour le formatage des chaînes semble certainement plus intuitif que pourcentage / modulo. La flèche vers la droite pour l'alignement à droite semble également assez intuitive.
Mark
2
@Mark Une façon dont l'ancienne méthode est plus propre est qu'elle utilise moins de caractères. Oui avec la familiarité, la nouvelle méthode devient intuitive mais elle n'est ni plus propre ni plus simple. L'ancienne méthode est plus intuitive pour ceux qui sont habitués à la syntaxe qui nous vient à travers le vénérable langage C, un langage d'une concision et d'une précision exemplaires. Quel précédent y a-t-il pour la nouvelle méthode?
Stephen Boston
2
@StephenBoston Je laisse la lisibilité aux experts, mais la nouvelle méthode est absolument plus propre. Les parents ne sont plus facultatifs. % peut être confondu avec un opérateur mathématique (bien que peu probable dans le contexte, mais en un coup d'œil sûr). L'ancienne méthode échouerait si le mot [n] n'est pas du type attendu (chaîne dans ce cas). La nouvelle méthode n'a pas besoin de savoir quel est le type entrant, cela fonctionne toujours. Propre et simple. Pour être honnête, je ne me suis jamais senti à l'aise avec le style printf (j'ai surtout fait du C avec cout).
Zim
53

Il peut être réalisé en utilisant rjust:

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

Vous pouvez l'aligner comme ça:

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

>signifie « aligner à droite » et 8correspond à la largeur d'une valeur spécifique.

Et voici une preuve:

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


       1      128  1298039
  123388        0        2

Ps. *linesignifie que la lineliste sera décompressée, donc .format(*line)fonctionne de manière similaire à .format(line[0], line[1], line[2])(en supposant qu'il lines'agit d'une liste avec seulement trois éléments).

Tadeck
la source
27

J'apprécie vraiment une nouvelle interpolation de chaîne littérale dans Python 3.6+:

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

Référence: PEP 498 - Interpolation de chaîne littérale

dmitry_romanov
la source
19

Voici une autre façon de formater en utilisant le 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}",
)

Cela fournira la sortie suivante:

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

Ce que vous faites ici, c'est que vous dites que la première colonne a une longueur de 15 caractères et qu'elle est justifiée à gauche et que la deuxième colonne (valeurs) a une longueur de 10 caractères et qu'elle est justifiée à droite.

Vlad Bezden
la source
Existe-t-il un moyen de paramétrer la largeur des formats? Dans cet exemple, si vous décidez de modifier la mise en forme en 20 et 15 largeurs, il faut changer plusieurs lignes. widths = [15, 10] f"{'Trades:':<width[0]}{cnt:>width[1]}",J'aimerais réaliser qc comme ci-dessus.
Tomasz Sabała
1
Je l'ai! Peut-être que quelqu'un trouvera cela utile. J'ai besoin d'un autre crochets imbriqués pour cela, donc:f"{'Trades:':<{width[0]}}{cnt:>{width[1]}}"
Tomasz Sabała
1
Parfois, les meilleures réponses sont celles qui ne répondent pas à la question exacte. Merci pour cela! :)
Brian Wiley
5

Tableau simple de la sortie:

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

production:

variable a    variable b
      0.33         66.67

% 10.2f: 10 est la longueur minimale et 2 est le nombre de décimales.

Thoran
la source
1

Pour le faire en utilisant f-string et avec le contrôle du nombre de chiffres de fin:

print(f'A number -> {my_number:>20.5f}')
L'apprentissage est un gâchis
la source