pythonlisttranspose

Transpose list of lists


Suppose I have

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

How can I get a result like so?

r = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

I know how to get

r = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

but I must have lists as elements of the result.


Solution

  • For rectangular data

    (or to limit each "column" to the length of the shortest input "row")

    In Python 3.x, use:

    # short circuits at shortest nested list if table is jagged:
    list(map(list, zip(*l)))
    

    In Python 2.x, use:

    # short circuits at shortest nested list if table is jagged:
    map(list, zip(*l))
    

    There are two important things to understand here:

    1. The signature of zip: zip(*iterables) This means zip expects an arbitrary number of arguments each of which must be iterable. E.g. zip([1, 2], [3, 4], [5, 6]).
    2. Unpacked argument lists: Given a sequence of arguments args, f(*args) will call f such that each element in args is a separate positional argument of f. Given l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], zip(*l) would be equivalent to zip([1, 2, 3], [4, 5, 6], [7, 8, 9]). See also: Expanding tuples into arguments

    The rest is just making sure the result is a list of lists instead of a list of tuples, by using map to create a list from each tuple.

    For jagged data

    To pad shorter rows with None values in the output, import itertools (this is in the standard library), and then:

    In Python 3.x, use:

    list(map(list, itertools.zip_longest(*l, fillvalue=None)))
    

    In Python 2.x, use:

    list(map(list, itertools.izip_longest(*l, fillvalue=None)))