I wanted to transpose list of lists in python 3 like:
[[1, 2, 3, 4], [5, 6, 7], [8, 9]] -> [[1, 5, 8], [2, 6, 9], [3, 7, 0], [4, 0, 0]]
Convert matrix or list of lists same size
The idea is to keep the longest list size without truncation of elements. Because if you use zip elements of the longer lists will be truncate:
listOfList = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
print(list(zip(*listOfList)))
result:
[(1, 5, 8), (2, 6, 9)]
Note the difference in the brackets: squared vs round is that squared are used for list and round for tuple:
- [1, 2, 3, 4] - list
- (1, 2, 3, 4) - tuple
So you can use zip when you have equally sized lists as:
listOfList = [[1, 2, 3], [5, 6, 7], [8, 9, 4]]
print(list(zip(*listOfList)))
result:
[(1, 5, 8), (2, 6, 9), (3, 7, 4)]
Convert list of lists different size
The simplest way to convert uneven list and preserving all elements would be by using zip_longest:
from itertools import zip_longest
listOfList = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
print(list(zip_longest(*listOfList)))
result:
[(1, 5, 8), (2, 6, 9), (3, 7, None), (4, None, None)]
The same example but this time outputing list of list, using 0 instead of None and using method:
from itertools import zip_longest
def transpose(lists):
return list(zip_longest(*lists,fillvalue=0))
listOfList = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
transposedList = [list(row) for row in transpose(listOfList)]
print(transposedList)
result:
[[1, 5, 8], [2, 6, 9], [3, 7, 0], [4, 0, 0]]
Python 2 version
This is the python 2 version and using 'x' as default element in case of missing one:
listofLists = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
import itertools
def transpose(lists):
return list(itertools.izip_longest(*lists,fillvalue='x'))
print(list(transpose(listofLists)))
result:
[(1, 5, 8), (2, 6, 9), (3, 7, 'x'), (4, 'x', 'x')]
Convert list of lists by using lambda expression
Another way to the the same transformation is by:
- find the longest list length
- iterate over all lists
- use lambda (anonymous function) in order to check the lenght
- same lenght - output the list
- shorter - add the difference with None - the python equivalent of null
listOfList = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
max = (max(map(lambda x: len(x), listOfList)))
transposedList = list(map(lambda x: x if len(x) == max else x + [None] * (max - len(x)) , listOfList))
for key in zip(*transposedList):
print(key)
Groovy version
Just for fun I will add similar code but this time in groovy:
def lists = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
(0..<(lists*.size().max())).collect {
mtrx*.getAt(it)
}
result:
[[1, 5, 8], [2, 6, 9], [3, 7, null], [4, null, null]]
This code is:
- find lenght - L of the longest list
- making "range" from 0 to the lenght - L - in groovy there aren't ranges
- iterating over the range
- get the elements of the matrix and add them to list(in case of missing one return null)