Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using rjust() and reducing for loops in Python

I'm trying to formulate a function that takes a list of lists of strings and displays it in a well-organized table with each column right-justified. Assume that all the inner lists will contain the same number of strings. For example, the value could look like this:

tableData = [['apples', 'oranges', 'cherries', 'banana'],

['Alice', 'Bob', 'Carol', 'David'],

['dogs', 'cats', 'moose', 'goose']]

Your function would print the following (right justified):

    apples Alice   dogs

   oranges   Bob   cats

  cherries Carol  moose

    banana David  goose

Using a given hint, I've arrived at:

def printable(tableData):
    newTable = np.zeros((len(tableData[0]),len(tableData)))
    colWidths = [0] * len(tableData)
    for i in range(0,len(tableData)):
        colWidths[i] = max(tableData[i], key=len)
    largest = max(colWidths, key=len)
    for i in range(0,len(tableData)):
        for j in range(0,len(tableData[0])):
            newTable[i][j] = tableData[j][i].rjust(len(largest))

I'm appalled at the no. of for loops. As a beginner, I'm still getting out of the 'for-loop' mode. Also, I'm pondering on the best form of attack for this problem. Thanks.

like image 495
srkdb Avatar asked Dec 17 '22 21:12

srkdb


1 Answers

Here's one way to do this in plain Python. We use zip to transpose the table so we can get the maximum width of each column.

table_data = [
    ['apples', 'oranges', 'cherries', 'banana'],
    ['Alice', 'Bob', 'Carol', 'David'],
    ['dogs', 'cats', 'moose', 'goose'],
]

# Determine the width of each column
widths = [max(map(len, column)) for column in zip(*table_data)]
new_table = [[s.rjust(w) for s, w in zip(row, widths)]
    for row in table_data]

for row in new_table:
    print(row)

output

['apples', 'oranges', 'cherries', 'banana']
[' Alice', '    Bob', '   Carol', ' David']
['  dogs', '   cats', '   moose', ' goose']

If you don't really need a new 2D list, and you just want to print the data, you can do something like this:

for row in table_data:
    print(*(s.rjust(w) for s, w in zip(row, widths)))

output

apples oranges cherries banana
 Alice     Bob    Carol  David
  dogs    cats    moose  goose

Here's a new version that transposes the table.

widths = [max(map(len, row)) for row in table_data]
new_table = [[s.rjust(w) for s, w in zip(row, widths)] for row in zip(*table_data)]
for row in new_table:
    print(row)

output

['  apples', 'Alice', ' dogs']
[' oranges', '  Bob', ' cats']
['cherries', 'Carol', 'moose']
['  banana', 'David', 'goose']
like image 79
PM 2Ring Avatar answered Jan 03 '23 02:01

PM 2Ring