1

I am trying to display a list in vertically sorted columns with number of columns decided by the user. I want to use zip() but I can't seem to figure out how to tell it to go through n no of lists.

#!/usr/bin/env python

import random

lst = random.sample(range(100), 30)
lst = sorted(lst)

col_size = int(raw_input('How many columns do you want?: '))
sorting = 'Vertical'

if sorting == 'Vertical':
    # vertically sorted
    columns = []
    n = len(lst)//col_size

    for i in range(0, len(lst), n):
        columns.append(lst[i:i+n])

    print '\nVertically Sorted:'

    print columns
    print zip(*columns)

This gives this result:

How many columns do you want?: 4

Vertically Sorted:
[[0, 2, 4, 11, 12, 16, 23], [24, 31, 32, 36, 41, 48, 50], [52, 54, 61, 62, 63, 64, 67], [76, 80, 81, 89, 91, 92, 94], [96, 97]]
[(0, 24, 52, 76, 96), (2, 31, 54, 80, 97)]

If I knew the number of columns (e.g. 4), I could've coded:

for c1, c2, c3, c4 in zip(columns[0], columns[1], columns[2], columns[3]):
    print str(c1), str(c2).rjust(8), str(c3).rjust(8), str(c4).rjust(8)

But since I don't, how do I use zip? As you can see I tried zip(*columns) but that failed due to unequal no. of items in the last list.

Clement J.
  • 3,012
  • 26
  • 29
koogee
  • 943
  • 3
  • 12
  • 24

3 Answers3

1

Zip doesn't do what you're after because the rows are different sizes. Map will transpose when rows are uneven.

See the following with code help from Create nice column output in python.

PROGRAM

import random

lst = random.sample(range(100), 30) lst = sorted(lst)

col_size = int(raw_input('How many columns do you want?: ')) sorting = 'Vertical'

if sorting == 'Vertical': # vertically sorted columns = [] n = len(lst)//col_size

for i in range(0, len(lst), n):
    columns.append(lst[i:i+n])

print '\nColumns:'
columns = map(None,*columns)
print columns
print '\nVertically Sorted:'

col_width = max(len(str(word)) for row in columns for word in row) + 2  # padding
for row in columns:
  print "".join(str(word).ljust(col_width) for word in row if word is not None)

OUTPUT

How many columns do you want?: 4

Columns:
[(0, 19, 45, 62, 92), (1, 24, 47, 64, 93), (5, 29, 48, 72, None), (6, 31, 50, 80, None), (9, 34, 56, 85, None), (14, 36, 58, 87, None), (15, 37, 61, 90, None)]

Vertically Sorted:
0     19    45    62    92
1     24    47    64    93
5     29    48    72
6     31    50    80
9     34    56    85
14    36    58    87
15    37    61    90
Community
  • 1
  • 1
Jonathan
  • 5,736
  • 2
  • 24
  • 22
0

Use the grouper recipe IT.izip_longest(*[iterable]*n) to collect the items in lst into groups of size n. (See this page for a more detailed explanation of how the grouper recipe works.)

import random
import itertools as IT
# lst = random.sample(range(100), 30)
lst = range(30)
lst = sorted(lst)

col_size = int(raw_input('How many columns do you want?: '))
sorting = 'Vertical'

if sorting == 'Vertical':
    # vertically sorted
    n = len(lst)//col_size
    lst = iter(lst)
    columns = IT.izip_longest(*[lst]*n, fillvalue='')

    print '\nVertically Sorted:'

    print('\n'.join(
        [''.join(map('{:4}'.format, row))
         for row in IT.izip(*columns)]))

yields

   0   7  14  21  28
   1   8  15  22  29
   2   9  16  23    
   3  10  17  24    
   4  11  18  25    
   5  12  19  26    
   6  13  20  27    
Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
0

Extend last list with None elements to get equal length, zip, after remove None elements from result.

eri
  • 3,133
  • 1
  • 23
  • 35