如何使用格式函数证明列的合理性?

How to justify columns using format function?

我有一个工作函数,它接受一个由列表组成的列表并将其输出为 table。我只是缺少某些间距和新行。我对格式化字符串(和一般的 python )还很陌生。如何使用格式化函数来修复我的输出?

例如:

>>> show_table([['A','BB'],['C','DD']])
'|  A   |   BB  |\n|    C   |   DD  |\n'


>>> print(show_table([['A','BB'],['C','DD']]))
|   A   |   BB  |
|   C   |   DD  |


>>> show_table([['A','BBB','C'],['1','22','3333']])
'|  A   |   BBB |   C               |\n|    1   |   22      |   3333    |\n'


>>> print(show_table([['A','BBB','C'],['1','22','3333']]))
|   A   |   BBB |   C               |
|   1   |   22      |   3333    |

我实际输出的是:

>>>show_table([['A','BB'],['C','DD']])
'| A | BB | C | DD |\n'

>>>show_table([['A','BBB','C'],['1','22','3333']])
'| A | BBB | C | 1 | 22 | 3333 |\n'


>>>show_table([['A','BBB','C'],['1','22','3333']])
| A | BBB | C | 1 | 22 | 3333 |

我肯定需要使用格式功能,但我不确定如何使用?

这是我当前的代码(我的缩进实际上是正确的,但我对 Whosebug 格式很糟糕):

def show_table(table):
 if table is None:
    table=[]
 new_table = ""
 for row in table:
    for val in row:
         new_table += ("| " + val + " ")
 new_table += "|\n"
 return new_table

您的函数中确实存在缩进错误:行

new_table += "|\n"

应该进一步缩进,以便它出现在每一行的末尾,而不是在 table.

的末尾

Side note: you'll catch this kind of thing more easily if you stick to 4 spaces per indent. This and other conventions are there to help you, and it's a very good idea to learn the discipline of keeping to them early in your progress with Python. PEP 8 is a great resource to familarise yourself with.

您的 "what I need" 示例中的间距也相当混乱,这很不幸,因为间距是您问题的主题,但我从 了解到您希望每一列都正确对齐,例如

>>> print(show_table([['10','2','300'],['4000','50','60'],['7','800','90000']]))
| 10   | 2   | 300   |
| 4000 | 50  | 60    |
| 7    | 800 | 90000 |

为此,您需要事先知道列中每个项目的最大宽度是多少。这实际上有点棘手,因为您的 table 被组织成行而不是列,但是 zip() 函数可以提供帮助。下面是 zip() 的一个例子:

>>> table = [['10', '2', '300'], ['4000', '50', '60'], ['7', '800', '90000']]
>>> from pprint import pprint
>>> pprint(table, width=30)
[['10', '2', '300'],
 ['4000', '50', '60'],
 ['7', '800', '90000']]
>>> flipped = zip(*table)
>>> pprint(flipped, width=30)
[('10', '4000', '7'),
 ('2', '50', '800'),
 ('300', '60', '90000')]

如您所见,zip() 将行变成列,反之亦然。 (现在不要太担心 table 之前的 * ;暂时解释起来有点高级。记住你需要它)。

你得到字符串的长度 len():

>>> len('800')
3

你得到列表中最大的项目 max():

>>> max([2, 4, 1])
4

您可以将所有这些放在一个 list comprehension 中,这就像一个构建列表的紧凑 for 循环:

>>> widths = [max([len(x) for x in col]) for col in zip(*table)]
>>> widths
[4, 3, 5]

如果你仔细看,你会发现那一行实际上有两个列表理解:

[len(x) for x in col]

使用列表 col 中每个项目 x 的长度创建一个列表,并且

[max(something) for col in zip(*table)]

为翻转后的每一列(使用 zip)创建一个最大值为 something 的列表 table ……其中 something 是另一个列表理解。

第一次看到时有点复杂,所以花点时间确保您了解发生了什么。

现在您已经设置了每列的最大宽度,您可以使用它们来设置输出格式。不过,为此,您需要跟踪自己所在的列,为此,您需要 enumerate()。这是 enumerate() 的一个例子:

>>> for i, x in enumerate(['a', 'b', 'c']):
...     print("i is", i, "and x is", x)
... 
i is 0 and x is a
i is 1 and x is b
i is 2 and x is c

如您所见,迭代 enumerate() 的结果会得到两个值:列表中的位置和项目本身。

还在我身边吗?很有趣,不是吗?按下...

唯一剩下的就是实际的格式化。 Python 的 str.format() 方法非常强大,但过于复杂,无法在此答案中进行透彻解释。你可以用它做的一件事是将东西填充到给定的宽度:

>>> "{val:5s}".format(val='x')
'x    '

在上面的示例中,{val:5s} 表示 "insert the value of val here as a string, padding it out to 5 spaces"。您还可以将宽度指定为变量,如下所示:

>>> "{val:{width}s}".format(val='x', width=3)
'x  '

这些都是您需要的部分……这是一个使用所有这些部分的函数:

def show_table(table):
    if table is None:
        table = []
    new_table = ""
    widths = [max([len(x) for x in c]) for c in zip(*table)]
    for row in table:
        for i, val in enumerate(row):
            new_table += "| {val:{width}s} ".format(val=val, width=widths[i])
        new_table += "|\n"
    return new_table

… 在这里它正在运行:

>>> table = [['10','2','300'],['4000','50','60'],['7','800','90000']]
>>> print(show_table(table))
| 10   | 2   | 300   |
| 4000 | 50  | 60    |
| 7    | 800 | 90000 |

我在这个答案中涵盖了相当多的基础知识。希望如果您详细研究了此处给出的 show_table() 的最终版本(以及整个答案中链接的文档),您将能够看到前面描述的所有部分是如何组合在一起的。