【问题标题】:Format output string, right alignment格式化输出字符串,右对齐
【发布时间】:2012-01-04 06:54:37
【问题描述】:

我正在处理一个包含坐标 x、y、z 的文本文件

     1      128  1298039
123388        0        2
....

每一行被分隔成3个项目使用

words = line.split()

处理数据后,我需要将坐标写回到另一个 txt 文件中,以便每列中的项目右对齐(以及输入文件)。每一行都是由坐标组成的

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

C++ 中是否有像std::setw() 之类的操纵器允许设置宽度和对齐方式?

【问题讨论】:

    标签: python alignment string-formatting


    【解决方案1】:

    这是另一种使用“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}",
    )
    

    这将提供以下输出:

    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
    

    你在这里所做的是你说第一列是 15 个字符长,它是左对齐的,第二列(值)是 10 个字符长,它是右对齐的。

    如果您加入列表中的项目,并且想要格式化项目之间的空间,您可以使用 `` 和常规格式化技术。

    此示例将每个数字用 3 个空格分隔。这里的关键是 f"{'':>3}"

    print(f"{'':>3}".join(str(i) for i in range(1, 11)))
    

    输出:

    1   2   3   4   5   6   7   8   9   10
    

    【讨论】:

    • 有没有办法对格式的宽度进行参数化?在此示例中,如果您决定将格式更改为 20 和 15 宽度,则需要更改多行。 widths = [15, 10]f"{'Trades:':&lt;width[0]}{cnt:&gt;width[1]}",我想实现上面那样的东西。
    • 知道了!也许有人会发现它有帮助。为此,我还需要一个嵌套括号:f"{'Trades:':&lt;{width[0]}}{cnt:&gt;{width[1]}}"
    • 有时最好的答案是那些没有回答确切问题的答案。谢谢你! :)
    • @BrianWiley 没错!我也在寻找格式化字符串文字。我总是忘记“string-in-string” hack(即在 ` " " ` 中使用 ` ' ' `)。
    【解决方案2】:

    将 Vlad 的精彩内容与其他内容混合,也可以编写代码以实现可读性和易用性,例如 ...

    >>> cnt = wins = losses      = str(   2)
    >>> evens = win_r = mean_w   = str(  14)
    >>> mean_l = mean_trd = sd   = str( 336)
    >>> max_l = max_w = sharpe_r = str(4278)
    >>>
    >>> rpad = 10
    >>>
    >>> print(
    ...     '\n Trades         ' +      cnt.rjust(rpad),
    ...     '\n Wins           ' +     wins.rjust(rpad),
    ...     '\n Losses         ' +   losses.rjust(rpad),
    ...     '\n Breakeven      ' +    evens.rjust(rpad),
    ...     '\n Win/Loss Ratio ' +    win_r.rjust(rpad),
    ...     '\n Mean Win       ' +   mean_w.rjust(rpad),
    ...     '\n Mean Loss      ' +   mean_l.rjust(rpad),
    ...     '\n Mean           ' + mean_trd.rjust(rpad),
    ...     '\n Std Dev        ' +       sd.rjust(rpad),
    ...     '\n Max Loss       ' +    max_l.rjust(rpad),
    ...     '\n Max Win        ' +    max_w.rjust(rpad),
    ...     '\n Sharpe Ratio   ' + sharpe_r.rjust(rpad),
    ... )
    
     Trades                  2
     Wins                    2
     Losses                  2
     Breakeven              14
     Win/Loss Ratio         14
     Mean Win               14
     Mean Loss             336
     Mean                  336
     Std Dev               336
     Max Loss             4278
     Max Win              4278
     Sharpe Ratio         4278
    

    【讨论】:

      【解决方案3】:

      通过使用 f-string 并控制尾随数字的数量来做到这一点:

      print(f'A number -> {my_number:>20.5f}')
      

      【讨论】:

        【解决方案4】:

        我真的很喜欢 Python 3.6+ 中的新文字字符串插值:

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

        参考:PEP 498 -- Literal String Interpolation

        【讨论】:

          【解决方案5】:

          使用较新的str.format syntax 尝试这种方法:

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

          下面是使用旧的% 语法的方法(适用于不支持str.format 的旧版Python):

          line_new = '%12s  %12s  %12s' % (word[0], word[1], word[2])
          

          【讨论】:

          • 请注意“旧”语法如何更简洁、更易于阅读和更短。
          • 我想我会添加一个比提供的链接更直接的链接:docs.python.org/2/library/…
          • 肯定更短,我不知道清洁剂的真正含义,但我认为“更易于阅读”只是因为它很熟悉。如果您还不熟悉其中之一,那么新格式似乎更易于阅读。用于字符串格式化的“.format”当然看起来比百分比/模数更直观。右对齐的右箭头似乎也很直观。
          • @Mark 一种更简洁的旧方法是使用更少的字符。是的,熟悉的新方法变得直观,但它并不干净和简单。对于那些习惯于通过古老的 C 语言(一种具有模范简洁性和精确性的语言)带给我们的语法的人来说,旧方法更直观。新方式有什么先例?
          • @StephenBoston 我将把可读性留给专家,但新方法绝对更干净。 Parens 不再是可选的。 % 可能会与数学运算符混淆(尽管在上下文中不太可能,但一目了然)。如果 word[n] 不是预期的类型(在这种情况下为字符串),旧方法将失败。新方法不需要知道传入的类型是什么,它总是有效的。干净简单。说句公道话,我对 printf 风格并不满意(我主要是用 cout 做 C 语言)。
          【解决方案6】:

          输出的简单列表:

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

          输出:

          variable a    variable b
                0.33         66.67
          

          %10.2f: 10 是最小长度,2 是小数位数。

          【讨论】:

            【解决方案7】:

            你可以这样对齐:

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

            其中&gt; 表示“右对齐”,8 是特定值的宽度

            这是一个证明:

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

            附言。 *line 表示line 列表将被解包,因此.format(*line) 的工作方式与.format(line[0], line[1], line[2]) 类似(假设line 是一个只有三个元素的列表)。

            【讨论】:

              【解决方案8】:

              可以通过rjust实现:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-10-10
                • 1970-01-01
                • 2022-06-22
                • 2012-03-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多