Formatear cadena de salida, alineación derecha

149

Estoy procesando un archivo de texto que contiene las coordenadas x, y, z

     1      128  1298039
123388        0        2
....

cada línea se delimita en 3 elementos usando

words = line.split()

Después de procesar los datos, necesito escribir las coordenadas en otro archivo txt para que los elementos de cada columna estén alineados a la derecha (así como el archivo de entrada). Cada línea está compuesta de las coordenadas.

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

¿Hay algún manipulador como std::setw()etc. en C ++ que permita establecer el ancho y la alineación?

justik
fuente

Respuestas:

230

Pruebe este enfoque utilizando la str.formatsintaxis más reciente :

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

Y aquí se explica cómo hacerlo utilizando la %sintaxis anterior (útil para versiones anteriores de Python que no son compatibles str.format):

line_new = '%12s  %12s  %12s' % (word[0], word[1], word[2])
Mark Byers
fuente
39
Observe cómo la sintaxis "antigua" es más limpia, más fácil de leer y más corta.
fyngyrz
2
Pensé que agregaría un enlace más directo que el proporcionado: docs.python.org/2/library/…
brw59
48
En resumen, no sé qué significa realmente limpiador, pero creo que "más fácil de leer" es solo porque es familiar. Si aún no está familiarizado con uno de ellos, el nuevo formato parece más fácil de leer. ".format" para el formateo de cadenas ciertamente parece más intuitivo que el porcentaje / módulo. La flecha hacia la derecha para la alineación hacia la derecha también parece bastante intuitiva.
Mark
2
@Mark Una forma en que la forma anterior es más limpia es que usa menos caracteres. Sí, con familiaridad, la nueva forma se vuelve intuitiva, pero no es más limpia y simple. La vieja forma es más intuitiva para aquellos que están acostumbrados a la sintaxis que nos llega a través del venerable lenguaje C, un lenguaje de concisión y precisión ejemplares. ¿Qué precedente hay para la nueva forma?
Stephen Boston
2
@StephenBoston Dejaré la legibilidad a los expertos, pero la nueva forma es absolutamente más limpia. Parens ya no son opcionales. % puede confundirse con un operador matemático (aunque no sea probable en contexto, pero a simple vista). La antigua forma fallaría si la palabra [n] no es del tipo esperado (cadena en este caso). La nueva forma no necesita saber cuál es el tipo entrante, siempre funciona. Limpio y sencillo. Para ser justos, nunca me sentí cómodo con el estilo printf (principalmente hice C con cout).
Zim
53

Se puede lograr mediante el uso de rjust:

line_new = word[0].rjust(10) + word[1].rjust(10) + word[2].rjust(10)
clwen
fuente
52

Puedes alinearlo así:

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

donde >significa " alinear a la derecha " y 8es el ancho de un valor específico.

Y aquí hay una prueba:

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


       1      128  1298039
  123388        0        2

PD. *linesignifica que la linelista se desempaquetará, por lo que .format(*line)funciona de manera similar a .format(line[0], line[1], line[2])(suponiendo que linesea ​​una lista con solo tres elementos).

Tadeck
fuente
19

Aquí hay otra forma de cómo puede formatear usando el formato '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}",
)

Esto proporcionará el siguiente resultado:

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

Lo que está haciendo aquí es decir que la primera columna tiene 15 caracteres de longitud y está justificada a la izquierda y la segunda columna (valores) tiene 10 caracteres de longitud y está justificada a la derecha.

Vlad Bezden
fuente
¿Hay alguna manera de parametrizar el ancho de los formatos? En este ejemplo, si decide cambiar el formato a 20 y 15 anchos, debe cambiar varias líneas. widths = [15, 10] f"{'Trades:':<width[0]}{cnt:>width[1]}",Me gustaría lograr algo como el anterior.
Tomasz Sabała
1
¡Entendido! Quizás alguien lo encuentre útil. Necesito un paréntesis anidado más para esto, así que:f"{'Trades:':<{width[0]}}{cnt:>{width[1]}}"
Tomasz Sabała
1
A veces las mejores respuestas son las que no responden la pregunta exacta. ¡Gracias por esto! :)
Brian Wiley
5

Tabulación simple de la salida:

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

salida:

variable a    variable b
      0.33         66.67

% 10.2f: 10 es la longitud mínima y 2 es el número de decimales.

Thoran
fuente
1

Para hacerlo usando f-string y con control del número de dígitos finales:

print(f'A number -> {my_number:>20.5f}')
Aprender es un desastre
fuente