gdogg371
gdogg371

Reputation: 4122

How to print a set of nested list as I need in Python 3.6

I have a nested containing values of different lengths as so:

[['cat', 123, 'yellow'],
['dog', 12345, 'green'],
[horse', 123456, 'red']]

I want to print them like this:

cat,   123,    yellow
dog,   12345,  green
horse, 123456, red 

I have tried using pprint to achieve my aims with the following code:

for sub in master_list:

    pp = pprint.PrettyPrinter(indent=4)
    pp.pprint(sub)

Where master is the nested list and sub the lists within it. This however gives me an output like so:

[
    'cat', 
    123, 
    'yellow'
],

[
    'dog', 
    12345, 
    'green'
],

[
    horse', 
    123456, 
    'red'
]

Is there a python module that allows me to relatively easily achieving what I want, without some sort of convoluted hack?

Thanks

Upvotes: 2

Views: 2024

Answers (6)

iGian
iGian

Reputation: 11183

Another way, given the nested list:

table = [['cat', 123, 'yellow'],
          ['dog', 12345, 'green'],
          ['horse', 123456, 'red']]

Using string methods:

for line in table:
  print("|", end='')
  for word in line:
    print (f" {word}".ljust(10) + "|", end='')
  print()

To get:

| cat      | 123      | yellow   |
| dog      | 12345    | green    |
| horse    | 123456   | red      |

Upvotes: 0

r.ook
r.ook

Reputation: 13858

You can do this:

spacing = [max(map(lambda x: len(str(x)), d)) for d in zip(*data)]
for row in data:
    for i, elem in enumerate(row):
        e = str(elem) + (',' if i < len(row) -1 else '')
        print('{{:{}}} '.format(spacing[i]+1).format(e), end='')
    print()

Results:

cat,      123,      orange  
elephant, 500000,   green   
horse,    123456.0, red  

Explanations:

spacing is defined by first gathering the maximum lengths of each "column" in your data. We can group the columns by using:

zip(*data)

Which gives a transposed copy of your data like this:

('cat', 'elephant', 'horse'), 
(123, 500000, 123456.0), 
('orange', 'green', 'red')

Then we use the map function to apply the len(str(x)) function over these columns:

(3, 8, 5),
(3, 6, 8), 
(6, 5, 3)

Then we just get the max of each column, combine everything in a list comprehension and return it as spacing:

spacing = [max(map(lambda x: len(str(x)), d)) for d in zip(*data)]

Then, while we loop through your data, we want to also enumerate(row) so we know which "column" we're working with. i will give you the index of the column in addition to the actual elem.

After that, we assign a temporary str to append the comma if it's not the last element:

e = str(elem) + (',' if i < len(row) -1 else '')

This makes it a bit more readable then adding it as part of the format params.

Afterwards we use string formatting (or e.ljust(spacing[i] + 1) if you wish) to add the predefined maximum spacing based on the column. Note we format the string twice by first escaping the outer curly brackets ({{ and }}), so it can be in sequence:

'{{:{}}}.format(9).format(e)
# becomes
'{:9}'.format(e)
# becomes
'cat,     '

Note the use of end='' to make the print line continuous until the row has finished. The spacing[i] + 1 is to account for the added comma.

I must confess this might not be the most efficient way, but depending on what you're trying to achieve the solution can be markedly different.

Upvotes: 1

quant
quant

Reputation: 2224

You may use the following code:

myLst = [['cat', 123, 'yellow'],
['dog', 12345, 'green'],
['horse', 123456, 'red']]

for subLst in myLst:
    print("\t".join([str(ele) for ele in subLst]))

Which is printing the output like so:

cat    123      yellow
dog    12345    green
horse  123456   red

In case you want to have "," too, just change the line

print("\t".join([str(ele) for ele in subLst]))

to

print(",\t".join([str(ele) for ele in subLst]))

And the complete thing as a one-liner:

print("\n".join([",\t".join([str(ele) for ele in subLst]) for subLst in myLst]))

Or in case you need a function:

def printLst(myLst):
    print("\n".join([",\t".join([str(ele) for ele in subLst]) for subLst in myLst]))

Edit

As pointed out in the comments this is also a good use-case for the python map function. Which can be used in order to make everything shorter ;)

Upvotes: 2

Rishabh
Rishabh

Reputation: 902

You can use this:

a = [['cat', 123, 'yellow'], ['dog', 12345, 'green'], ['horse', 123456, 'red']]

# Get the max length of string in the list
m = max([len(str(x)) for y in a for x in y])

# Use the format specifier in Python print function:
# Example: print '{:10s} {:3d}  {:7.2f}'.format('xxx', 123, 98)
# This prints : xxx        123    98.00
# We will create the string as {:6s}, here 6 is the length in our case and will be generated dynamically using 'm'

list(map(lambda x: print('\t'.join(list(map(lambda y:   str('{' + ':{m}s'.format(m=m) +'}').format(str(y)), x)))), a))

Output:

cat     123     yellow
dog     12345   green 
horse   123456  red

Upvotes: 0

Patrick Artner
Patrick Artner

Reputation: 51643

Your concrete format wishescan be solved by printing with ljust to add the needed spaces:

data = [['cat', 123, 'yellow'],
        ['dog', 12345, 'green'],
        ['horse', 123456, 'red']]

# get the overall widest string as base for right-aligning them 
max_len = max( len(str(x)) for k in data for x in k) 

for inner in data:
    first = True
    for elem in inner[:-1]: # all but the last
        text = "{},".format(elem).ljust(max_len+2)
        print(text,end="")

    print(inner[-1]) # print last

Output:

cat,    123,    yellow
dog,    12345,  green
horse,  123456, red

Doku:


Generally for formatting you can use the string format mini language to format your output to your liking:

for inner in data:
    first = True
    for elem in inner:
        if first:
            text = "{:<{}} ".format(elem,max_len+2)
            first = False
        else:
            text = ", {:<{}} ".format(elem,max_len+2)
        print(text, end="")
    print("")

Output:

cat      , 123      , yellow   
dog      , 12345    , green    
horse    , 123456   , red      

The format string "{:<{}} ".format(elem,max_len+2) formats element rightaligned into max_len+2 characters. The first thing is just to make your , not appear on the start of the line.

Upvotes: 1

Srce Cde
Srce Cde

Reputation: 1824

Pandas can help.

import pandas as pd
lst = [['cat', 123, 'yellow'], ['dog', 12345, 'green'], ['horse', 123456, 'red']]
df = pd.DataFrame(lst)
print(df)

Output:

    0   1   2
0   cat     123     yellow
1   dog     12345   green
2   horse   123456  red

Upvotes: 2

Related Questions