2

I'm struggling to align some data after iterating it through a for loop. I'd like to have each for loop output a separate column but failing to figure out how to accomplish this. I've tried ending with end='' for new lines but does not bring the next column back top. Can you please help? Below is a testable example of the code I am trying to build. Your help is well appreciated.

import time, re, collections, operator

output_list = [['2016-07-12', 'Magazine', 'News Paper #2', 'Podcast', '1234567', '10-10-10-10', 'ABCDEFG', 'Zoo'],
['2016-07-12', 'Book', 'News Paper #2', 'Podcast', '1234567', '10-10-10-10', 'ABCDEFG', 'Zoo'],
['2016-07-13', 'Book', 'News Paper #2', 'Podcast', '1234567', '10-10-10-10', 'ABREF', 'Zoo'],
['2016-07-14', 'Article', 'News Paper #4', 'Radio', '1234567', '10-10-10-10', 'ABCDEFG', 'Zoo'],
['2016-07-15', 'Article', 'News Paper #4', 'Radio', '1234567', '10-10-10-10', 'ABCDEFG', 'Zoo'],
['2016-07-15', 'Snippet', 'News Paper #2', 'Podcast', '1234567', '10-10-10-10', 'ABCDEFG', 'Zoo']]


def count_types():
    #item_1 = mm_counts(0)
    item_2 = mm_counts(1)
    item_3 = mm_counts(2)
    item_4 = mm_counts(3)
    item_5 = mm_counts(4)
    item_6 = mm_counts(5)
    item_7 = mm_counts(6)
    item_8 = mm_counts(7)

print('=' * 90)
print(('Media1    Media2    Media3    Media4    Media5    Media6    Media7'))
print('=' * 90)
def mm_counts(a):
    r = []
    for i in output_list:
        x = (i[a])
        r.append(x)
    y = collections.Counter(r)

    padding = 9
    for k, v in sorted(y.items(), key=operator.itemgetter(1), reverse=True):
        z = (str(k).ljust(13, ' ') + ' ' + (str(v).ljust(5, ' ')))
        print (z)

count_types()

Current Output:

==========================================================================================
Media1    Media2    Media3    Media4    Media5    Media6    Media7
==========================================================================================
Article       2    
Book          2    
Snippet       1    
Magazine      1    
News Paper #2 4    
News Paper #4 2    
Podcast       4    
Radio         2    
1234567       6    
10-10-10-10   6    
ABCDEFG       5    
ABREF         1    
Zoo           6    

Desired Output:

=============================================================================================
Media1       Media2            Media3      Media4      Media5           Media6      Media7
==============================================================================================
Article   2  Magazine       1  Podcast  4  1234567  6  10-10-10-10   6  ABCDEFG  5  Zoo  6 
Book      2  News Paper #2  4  Radio    2               ABREF    1
Snippet   1  News Paper #4  2    
Magazine  1 
MBasith
  • 1,407
  • 4
  • 29
  • 48
  • 1
    Can't you store all the data initially in `lists` and then `zip` them (or iterate over them together) before printing? – Chris_Rands Jul 14 '16 at 15:37
  • Just do `from __future__ import print_function` and consecutively executing `print("...", end="")` should not break the line. [How to print in Python without newline or space?](http://stackoverflow.com/questions/493386/how-to-print-in-python-without-newline-or-space) – Michael Hoff Jul 14 '16 at 15:38
  • 1
    @MichaelHoff, I tried that but it just prints all the lines in one row and not as columns. If it has worked for you can you please post the modified code? – MBasith Jul 14 '16 at 15:44
  • @MutationalMeltdown I tried to read up on zip but not familiar enough with to understand where I would insert it into the code. Can you provide some input on where I would place that in the code? – MBasith Jul 14 '16 at 15:46

1 Answers1

1

Learn to use the .format method (of a format string). You can specify field length, left/centre/right justification, decimal places and/or leading zeros of numeric values, and much more. https://docs.python.org/3/library/string.html#formatspec

An example

>>> kvp = [('Newspaper', 47), ('TV', 192), ('Radio', 543)]
>>> fs = '{0[0]:>10s} {0[1]:6d}'
>>> '    '.join( [ fs.format(kv) for kv in kvp ] )
' Newspaper     47            TV    192         Radio    543    '

Quite a bit going on there. fs is a format string. {...} in a format string mark items to format. Inside the braces the thing before the : identifies what to format and the stuff after, how to format it. 0[0] and 0[1] are the first and second elements of the first (here only) argument of the .format method (which has to be subscript-able). >10s means right-justify a string in a field-width of 10. 6d means decimal integer in a field width of 6.

Finally ' '.join( [ fs.format(kv) for kv in kvp ] ) creates a list of formatted elements of kvp (i.e. strings) and concatenates them all with four spaces between them (but no four leading or trailing spaces).

(Yes, this is a partial answer. Someone else can answer putting the right entities in the right order to format into the desired lines of output, if I mis-interpreted "align" in the question)

nigel222
  • 7,582
  • 1
  • 14
  • 22
  • Thanks for the response. I tried that as well and it does get the text into alignment if the value is only one item. However, i am iterating through multiple values so it doesn't quite work when there are multiple values per column. – MBasith Jul 14 '16 at 16:29
  • Isn't that what I showed you with `.join`? `kvp` is a list of tuples, the list is of arbitrary length. Each tuple is turned into a (here fixed-length) string via `.format` and these formatted strings are then joined together to make a line of output. If the issue is how to reorder your input data into something like the example's `kvp`, I didn't find the question entirely clear. Ask again with the emphasis on ordering not formatting? – nigel222 Jul 14 '16 at 16:35
  • Okay, sorry, I am very new to python. This is is what I added but did not accomplish putting them in column. Can you please let me know what I am doing wrong. `fs = '{0[0]:>10s} {0[1]:6d}' for kv in sorted(y.items(), key=operator.itemgetter(1), reverse=True): print(' '.join([fs.format(kv)]))` – MBasith Jul 14 '16 at 17:10