aero
aero

Reputation: 270

Print a list of lists as a table in Python

I've a list,

L = [['First', 'Last', 'GPA', 'Major', 'Drops'],
['Jane', 'Doe', '3.5', 'CS', '2'], ['Joe', 'Doe', '2.0', 'CpE', '0'],
['Todd', 'Brown', '3.88', 'CS', '5'], 
['Mike', 'Smith', '3.88', 'CS', '5']]

And I've to print it in a table like:

    --------------------------------------------------------
    |     First|      Last|       GPA|     Major|     Drops|
    --------------------------------------------------------
    |      Jane|       Doe|      3.50|        CS|         2|
    |       Joe|       Doe|      2.00|       CpE|         0|
    |      Todd|     Brown|      3.88|        CS|         5|
    |      Mike|     Smith|      3.88|        CS|         5|

My code is so far:

    L = [['First', 'Last', 'GPA', 'Major', 'Drops'],
     ['Jane', 'Doe', '3.5', 'CS', '2'],
     ['Joe', 'Doe', '2.0', 'CpE', '0'],
     ['Todd', 'Brown', '3.88', 'CS', '5'],
     ['Mike', 'Smith', '3.88', 'CS', '5']]
count1 = 1
while count1 < len(L):
    L[count1][2] = float(L[count1][2])
    L[count1][4] = int(L[count1][4])
    count1 += 1
h_line = 56 * '-'
first_line = "|"
print (h_line)
s = " "
w = 10
for i in range(len(L[0])):
    str1 = (s*(w - len(L[0][i])) + "%s|" % L[0][i])
    first_line = first_line + str1
print(first_line)
print(h_line)
a = 1
while a < len(L):
    second_line = "|"
    for j in range (len(L[a])):
        if type(L[a][j]) == str :
            str2 = (s*(w - len(L[a][j])) + ("%s|" % L[a][j]))
            second_line = second_line + str2
        elif type(L[a][j]) == float :
            str2 = (s*(w-4) + ("%.2f|" % L[a][j]))
            second_line = second_line + str2
        elif type(L[a][j]) == float :
            str2 = (s*(w-1) + ("%i|" % L[a][j]))
            second_line = second_line + str2
    print (second_line)
    a = a + 1


print (h_line)

But my output looks like:

    --------------------------------------------------------
    |     First|      Last|       GPA|     Major|     Drops|
    --------------------------------------------------------
    |      Jane|       Doe|      3.50|        CS|
    |       Joe|       Doe|      2.00|       CpE|
    |      Todd|     Brown|      3.88|        CS|
    |      Mike|     Smith|      3.88|        CS|
    --------------------------------------------------------

I can't figure out what I'm doing wrong.

Upvotes: 1

Views: 460

Answers (2)

user1630938
user1630938

Reputation:

Just an alternative, maybe not the case, but could be useful.

pip install tabulate

Note: I've get some errors installing with pip or easy_install.
Succeed to install it by downloading tabulate 0.7.3.tar.gz
and install it with: python setup.py install


See it in action (Your case):

from tabulate import tabulate

L = [['First', 'Last', 'GPA', 'Major', 'Drops'],
['Jane', 'Doe', '3.5', 'CS', '2'], 
['Joe', 'Doe', '2.0', 'CpE', '0'],
['Todd', 'Brown', '3.88', 'CS', '5'], 
['Mike', 'Smith', '3.88', 'CS', '5']]

print tabulate(L[1:], headers = L[0],tablefmt="grid")

Output:

>>> 
+---------+--------+-------+---------+---------+
| First   | Last   |   GPA | Major   |   Drops |
+=========+========+=======+=========+=========+
| Jane    | Doe    |  3.5  | CS      |       2 |
+---------+--------+-------+---------+---------+
| Joe     | Doe    |  2    | CpE     |       0 |
+---------+--------+-------+---------+---------+
| Todd    | Brown  |  3.88 | CS      |       5 |
+---------+--------+-------+---------+---------+
| Mike    | Smith  |  3.88 | CS      |       5 |
+---------+--------+-------+---------+---------+
>>> 

Bibliography:
tabulate 0.7.3 : Python Package Index http://goo.gl/OkEF5E

Upvotes: 2

Adam Smith
Adam Smith

Reputation: 54223

Holy crud is this ever the wrong way to go about this!!! Use string formatting

L = [['First', 'Last', 'GPA', 'Major', 'Drops'],
     ['Jane', 'Doe', '3.5', 'CS', '2'], ['Joe', 'Doe', '2.0', 'CpE', '0'],
     ['Todd', 'Brown', '3.88', 'CS', '5'], 
     ['Mike', 'Smith', '3.88', 'CS', '5']]

def display_table(rows):
    template = "|{:>10}|{:>10}|{:>10}|{:>10}|{:>10}|"
    horiz_rule = "-" * 56
    header = rows[0]
    print(horiz_rule)
    print(template.format(*header))
    print(horiz_rule)
    for row in rows[1:]:
        print(template.format(*row))
    print(horiz_rule)

display_table(L)

If you need to be able to programatically assign column widths, you can use an extra { and } to escape the outer formats, e.g.

template = "|{{:>{0}}}".format(some_width) * num_columns + "|"
## if some_width is 10 and num_columns is 5, 
## results in the same template as above. Then you can do:
horiz_rule = 1 + some_width * (num_columns + 1)

As a working example, Maybe you wanted to extend each column to a minimum of 10 spaces, but wanted to align to the longest element in that column plus 1.

def display_table(rows):
    # might want a sanity check here to make sure the table is square
    num_columns = len(rows)
    template = "|{{:>{}}}" * len(rows[0]) + "|"
    header = rows[0]
    # zip(*iterable) is a good recipe for aligning columnwise
    column_lengths = [max(10, max(map(len, col)) + 1) for col in zip(*rows)]
    finished_template = template.format(*column_lengths)
    hr = "-" * (sum(column_lengths) + num_columns + 1)
    print(hr)
    print(finished_template.format(*header))
    print(hr)
    for row in rows[1:]:
        print(finished_template.format(*row))
    print(hr)
display_table(L)

results in:

--------------------------------------------------------
|     First|      Last|       GPA|     Major|     Drops|
--------------------------------------------------------
|      Jane|       Doe|       3.5|        CS|         2|
|       Joe|       Doe|       2.0|       CpE|         0|
|      Todd|     Brown|      3.88|        CS|         5|
|      Mike|     Smith|      3.88|        CS|         5|
--------------------------------------------------------

Or if you add a student whose last name is "SomeReallyLongName":

L.append(['Foo','SomeReallyLongName','2.0','Mus','10'])
display_table(L)
## OUTPUT
------------------------------------------------------------------
|     First|               Last|       GPA|     Major|     Drops|
------------------------------------------------------------------
|      Jane|                Doe|       3.5|        CS|         2|
|       Joe|                Doe|       2.0|       CpE|         0|
|      Todd|              Brown|      3.88|        CS|         5|
|      Mike|              Smith|      3.88|        CS|         5|
|       Foo| SomeReallyLongName|       2.0|       Mus|        10|
------------------------------------------------------------------

Looks like that last bit has an off-by-one error in calculating the horizontal rule. It looks good to me, but obviously it's off (by one!) I'll leave squashing that as an exercise for the reader.

Upvotes: 8

Related Questions