漂亮地打印二维列表?

98

有没有一种简单的内置方法可以将Python的二维列表打印成二维矩阵?

像这样:

[["A", "B"], ["C", "D"]]

会变成类似于以下的内容

A    B
C    D

我找到了pprint模块,但它似乎不能满足我的需求。


6
我会把那个称为“三维列表”。如果您愿意使用,numpy对这种情况非常擅长。 - tacaswell
实际上,print 有一种非常巧妙的方法来处理这样的事情。有一个 end = foo 参数,允许您自定义在打印语句结尾处放置什么内容(默认为 \n)。请参考我的答案以备将来参考:https://dev59.com/YGYs5IYBdhLWcg3wAfPO#73229153。 - ᴇɴᴅᴇʀᴍᴀɴ
这个例子最简单的解决方案就是 for x in your_list: print(x) - Petr L.
12个回答

99

让事情变得有趣,我们来试试更大的矩阵:

matrix = [
   ["Ah!",  "We do have some Camembert", "sir"],
   ["It's a bit", "runny", "sir"],
   ["Well,",  "as a matter of fact it's", "very runny, sir"],
   ["I think it's runnier",  "than you",  "like it, sir"]
]

s = [[str(e) for e in row] for row in matrix]
lens = [max(map(len, col)) for col in zip(*s)]
fmt = '\t'.join('{{:{}}}'.format(x) for x in lens)
table = [fmt.format(*row) for row in s]
print '\n'.join(table)

输出:

Ah!                     We do have some Camembert   sir            
It's a bit              runny                       sir            
Well,                   as a matter of fact it's    very runny, sir
I think it's runnier    than you                    like it, sir  

更新:对于多行单元格,可以采用以下方式:

text = [
    ["Ah!",  "We do have\nsome Camembert", "sir"],
    ["It's a bit", "runny", "sir"],
    ["Well,",  "as a matter\nof fact it's", "very runny,\nsir"],
    ["I think it's\nrunnier",  "than you",  "like it,\nsir"]
]

from itertools import chain, izip_longest

matrix = chain.from_iterable(
    izip_longest(
        *(x.splitlines() for x in y), 
        fillvalue='') 
    for y in text)

然后应用上述代码。

另请参见http://pypi.python.org/pypi/texttable


太棒了!但是,如果我们想在每个单元格内有多行,例如一个3D数组呢 :) - CpILL
@CpILL:一个选项是将3D解压缩为2D:[[[a,b,c],[xyz]]]=>[[a,x],[b,y],[c,z]],然后应用上述方法。 - georg
你的意思是将数据透视吗? - CpILL
@CpILL:添加了一个示例。 - georg
我们如何将表格限制在前10个值呢? - Brendan Metcalfe

70

对于没有第三方库的Python 3:

matrix = [["A", "B"], ["C", "D"]]

print('\n'.join(['\t'.join([str(cell) for cell in row]) for row in matrix]))

输出

A   B
C   D

这里有一个被低估的答案。它非常好用,保持本地化,一行代码就能胜任。 - alphazwest
我唯一的遗憾是我只能给这个答案一个赞。 - DanWebster
1
我们应该给这个人颁发奖章。 - Philippe Remy

57

如果您会使用Pandas(Python数据分析库),那么您可以通过将其转换为DataFrame对象来漂亮地打印二维矩阵:

from pandas import *
x = [["A", "B"], ["C", "D"]]
print DataFrame(x)

   0  1
0  A  B
1  C  D

9
虽然这个回答可能是正确和有用的,但最好还是在其中加入一些解释来说明它如何帮助解决问题。如果未来发生了(可能不相关的)更改导致它停止工作,用户需要了解它曾经是如何工作的,此时解释就变得尤为重要。 - Kevin Brown-Silva
3
这正是我想要的。谢谢。 - Arvind

40

您总是可以使用numpy:

import numpy as np
A = [['A', 'B'], ['C', 'D']]
print(np.matrix(A))

输出:

[['A' 'B']
 ['C' 'D']]

2
展示输出结果以便与其他解决方案进行比较将是一个“不错的附加功能”。 - vwvan
1
使用 print(np.array(A)) 来避免警告。 - lingjiankong

12

为了提供一个更简单的替代方案print('\n'.join(\['\t'.join(\[str(cell) for cell in row\]) for row in matrix\])) :

matrix = [["A", "B"], ["C", "D"]]
for row in matrix:
    print(*row)

解释 *row 解包 row,所以当 row["A", "B"] 时,会调用 print("A", "B")

注意 只有每列具有相同的宽度,两个答案才能得到良好的格式化。要更改分隔符,请使用 sep 关键字。例如,

for row in matrix:
    print(*row, sep=', ')

will print

A, B
C, D

不使用for循环的单行代码实现

print(*(' '.join(row) for row in matrix), sep='\n')

' '.join(row) for row in matrix)会为每一行返回一个字符串,例如当row["A", "B"]时,它会返回A B

*(' '.join(row) for row in matrix), sep='\n')展开生成器返回序列'A B', 'C D',因此对于给定的示例matrix,会调用print('A B', 'C D', sep='\n')


1
好东西,嗯。 - A. Abramov
如果这些项的长度不同怎么办? - ᴇɴᴅᴇʀᴍᴀɴ

10

不使用任何第三方库,你可以这样实现:

matrix = [["A", "B"], ["C", "D"]]
print(*matrix, sep="\n")

输出:

['A', 'B']
['C', 'D']

也许人们想要比那更漂亮的东西... - ᴇɴᴅᴇʀᴍᴀɴ
如果矩阵非常大,有很多小数点等,则此方法将无法工作。它需要高级格式化,而您的答案中缺少这种格式化。 - Ash

6
比起使用 pandas,更加轻量级的方法是使用 prettytable 模块。
from prettytable import PrettyTable

x = [["A", "B"], ["C", "D"]]

p = PrettyTable()
for row in x:
    p.add_row(row)

print p.get_string(header=False, border=False)

yields:

A B
C D
< p >prettytable 有很多选项可以以不同的方式格式化您的输出。

请参见https://code.google.com/p/prettytable/获取更多信息。


6

如果你正在使用 Notebook/IPython 环境,则 sympy 可以使用 IPython.display 打印出漂亮的矩阵:

import numpy as np
from sympy import Matrix, init_printing
init_printing()

print(np.random.random((3,3)))
display(np.random.random((3,3)))
display(Matrix(np.random.random((3,3))))

enter image description here


3

我还建议使用tabulate,它可以选择性地打印标题:

from tabulate import tabulate

lst = [['London', 20],['Paris', 30]]
print(tabulate(lst, headers=['City', 'Temperature']))

:

City      Temperature
------  -------------
London             20
Paris              30

1

一种更简单的方法是使用print()中的"end"参数。这只能在Python(和许多其他语言)中起作用,因为所有字母的宽度都相同。

table = [["A", "BC"], ["DEFG", "HIJ"]]
for row in table:
    for col in row:
        spaces = 5 #adjust as needed
        spaces -= (len(col) - 1) #spaces everything out
        print(col, end = " " * spaces)
    print() #add line break before next row

"end"函数设置在参数结束后将打印什么,因为默认值是\n

正如您所看到的,我根据每行中每个项目的长度偏移了有多少个空格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接