首页 > 解决方案 > 选项卡在某些迭代中跳过

问题描述

我正在尝试打印列表列表并希望不同的列有一个选项卡。它适用于除第 3 行和第 5 行之外的所有内容。不知道为什么!

import csv
FILENAME = "BaseballPlayers.csv"


#def display_lineup():

player_list = []
with open(FILENAME, newline="") as file:
    reader = csv.reader(file)
    for row in reader:
        player_list.append(row)
    
for i in range(len(player_list)):
    player = player_list[i]
    print(str(i+1) + ". " + player[0]+ "\t" + player[1]+ "\t" +player[2]+ "\t" +player[3])

输出:

标签: pythonlistcsv

解决方案


这不是选项卡被跳过的问题,而是选项卡工作方式的基本怪癖。Tabbing 会将您带到下一个制表位,这可能并不总是相同的位置,具体取决于之前发生的情况。当您的播放器名称少于 5 个字符时,例如在“Tony”中,下一个制表位是“Tony”结束后的一个空格。

如果我将代码中的输出复制到显示空白字符的文本编辑器中,它看起来是这样的:

在此处输入图像描述

显然,标签在那里,但不是“足够大”

一种解决方案是填充空格以将列值增加到最大列表,然后使用制表符。

max_col_width = None
player_list = []
with open(FILENAME, newline="") as file:
    reader = csv.reader(file)
    for row in reader:
        if max_col_width is None:
            # This is the first row, set the lengths of each column as the max
            max_col_width = [len(c) for c in row]
        else:
            # For each column, the max is the larger of the 
            # existing max and the current column's length
            max_col_width = [max(m, len(c)) for m, c in zip(max_col_width, row)]
        player_list.append(row)

zip接受两个迭代并同时迭代它们,所以for m, c in zip(max_col_width, row)和做的一样

for i in len(row):
    m = max_col_width[i]
    c = row[i]

如果我们 print max_col_width,我们可以看到值:[7, 2, 3, 3]。所以我们需要将第一列中的每个元素填充为 7 的长度,将第二列中的每个元素填充为 2 的长度,依此类推。我们可以str.ljust()在打印之前使用左对齐所有字符串:

for i, player in enumerate(player_list):
    player = player_list[i]
    print(str(i+1) + ". " + player[0].ljust(max_col_width[0]) + "\t" + player[1].ljust(max_col_width[1]) + "\t" +player[2].ljust(max_col_width[2]) + "\t" +player[3].ljust(max_col_width[3]))

或者上述更 Pythonic 的方式是使用生成器并str.join()ljust

for i, player in enumerate(player_list):
    player = player_list[i]
    print(str(i+1) + ". " + "\t".join(p.ljust(l) for p, l in zip(player, max_col_width)))

现在我们有了将每个名称的长度扩展到最大长度的空格,并且制表符按我们想要的方式工作。

在此处输入图像描述

作为文本,我们得到以下输出:

1. Trevor   SS  588 173
2. Garrett  2B  299 74 
3. Tony     C   535 176
4. Hunter   RF  580 182
5. Ian      CF  443 113
...

当然,由于您已经在填充内容,因此您可以\t完全消除该字符并使用任意数量的空格(在下面的示例中为 4)来获得列之间的一致间距。

for i, player in enumerate(player_list):
    player = player_list[i]
    print(str(i+1) + ". " + (" " * 4).join(p.ljust(l) for p, l in zip(player, max_col_width)))
    # Or alternatively, 
    # print(str(i+1) + ". " + "".join(p.ljust(l + 4) for p, l in zip(player, max_col_width)))

在此处输入图像描述


推荐阅读