Python: wrapping uneven rows in columns

I have a list of lists with an odd number of items:

[['a','b','c'], ['d','e'], [], ['f','g','h','i']] 

I am showing a table in Reportlab and I want to display them as columns. As far as I understand, RL takes only the data for the tables (Platypus) in the form of a row, which I have above.

I can use a loop to make a switch, but I feel like there is a list that will be faster and more Pythonic. I will need empty space in columns that also exhaust elements.

Product Required:

 [['a','d','','f'],['b','e','','g'],['c','','','h'],['','','','i']] 

EDIT: example should be a string, not numbers

Thanks for the help!

+4
source share
5 answers

itertools.izip_longest() takes a fillvalue argument. On Python 3, it itertools.zip_longest() .

 >>> l = [[1,2,3], [4,5], [], [6,7,8,9]] >>> import itertools >>> list(itertools.izip_longest(*l, fillvalue="")) [(1, 4, '', 6), (2, 5, '', 7), (3, '', '', 8), ('', '', '', 9)] 

If you need sublists instead of tuples:

 >>> [list(tup) for tup in itertools.izip_longest(*l, fillvalue="")] [[1, 4, '', 6], [2, 5, '', 7], [3, '', '', 8], ['', '', '', 9]] 

Of course, this also works for strings:

 >>> l = [['a','b','c'], ['d','e'], [], ['f','g','h','i']] >>> import itertools >>> list(itertools.izip_longest(*l, fillvalue="")) [('a', 'd', '', 'f'), ('b', 'e', '', 'g'), ('c', '', '', 'h'), ('', '', '', 'i')] 

It even works like this:

 >>> l = ["abc", "de", "", "fghi"] >>> list(itertools.izip_longest(*l, fillvalue="")) [('a', 'd', '', 'f'), ('b', 'e', '', 'g'), ('c', '', '', 'h'), ('', '', '', 'i')] 
+10
source

Here is another way:

 >>> map(lambda *z: map(lambda x: x and x or '', z), *l) [['a', 'd', '', 'f'], ['b', 'e', '', 'g'], ['c', '', '', 'h'], ['', '', '', 'i']] 
+1
source

another way that in my opinion is simpler if you can wrap None values ​​instead of empty lines:

 a = [['a','b','c'], ['d','e'], [], ['f','g','h','i']] map(lambda *z: list(z), *a) #[['a', 'd', None, 'f'], ['b', 'e', None, 'g'], ['c', None, None, 'h'], [None, None, None, 'i']] 
0
source
 map(lambda *z: [s if s else '' for s in z], *a) 

or

 map(lambda *z: [('', s)[s>None] for s in z], *a) 
0
source
 grid = [['a','b','c'], ['d','e'], [], ['f','g','h','i']] i = 0 result = [] do_stop = False while not do_stop: result.append([]) count = 0 for block in grid: try: result[i].append(block[i]) except: result[i].append('') count = count +1 continue if count ==len(grid): result.pop(i) do_stop = True i = i + 1 print result 
0
source