3

I have a list of N lists, each sub-list containing M elements.

How do I create a list of M lists with N elements each, containing the n-th elements from the initial lists?

Let's say I have this

myList = [[1, 2, 3],[4, 5, 6]]

I want to have

[[1, 4],[2, 5],[3, 6]]

Performance is also important. I have sublists of millions of elements (though, one dimension will always be small: like 1.000.000 x 8 )

Sam
  • 19,708
  • 4
  • 59
  • 82

5 Answers5

3

This will give tuples, but it's trivial to extend this to contain lists:

zip(*myList)

i.e.

[list(i) for i in zip(*myList)]
filmor
  • 30,840
  • 6
  • 50
  • 48
3
>>> lst = [[1, 2, 3], [4, 5, 6]]
>>> zip(*lst)
[(1, 4), (2, 5), (3, 6)]

zip returns a list in Python 2, but an iterator in Python 3, which you have to convert to a list if you need to (list(zip(lst)))

See also: Matrix Transpose in Python, Transpose/Unzip Function (inverse of zip)?


What zip(*lst) does is unpacks the elements of lst using the * operator into separate arguments of the zip function.

We know what happens when we put two lists in:

>>> zip([1, 2, 3], [4, 5, 6])
[(1, 4), (2, 5), (3, 6)]

So if we have a list containing those two lists, the * will unpack the list to form two separate arguments - the equivalent of the above call.

>>> zip(*[[1, 2, 3], [4, 5, 6]])
[(1, 4), (2, 5), (3, 6)]
Community
  • 1
  • 1
Volatility
  • 31,232
  • 10
  • 80
  • 89
3

Use

myList = [[1, 2, 3],[4, 5, 6]] 
zip(*myList )
Arty
  • 579
  • 1
  • 8
  • 17
2

Maybe with the help of itertools.izip()

itertools.izip(*myList)

To create lists from this iterator do the following:

map(list, itertools.izip(*myList))
jamylak
  • 128,818
  • 30
  • 231
  • 230
Cédric Julien
  • 78,516
  • 15
  • 127
  • 132
0

Since you mentioned efficiency, I tried these with PyPy and somewhere around 100x1000 they start to be better than zip (on CPython however they are worse):

myList = [[1, 2, 3],[4, 5, 6]]
newList = [[] for _ in xrange(len(myList[0]))]
    for innerList in myList:
        for elIdx in xrange(len(innerList)):
            newList[elIdx].append(innerList[elIdx])

print newList

And my first attempt (which is worse), but still better then zip on PyPy:

newList = [[None for i in xrange(len(myList))] for j in xrange(len(myList[0]))]
for i in xrange(len(myList)):
    for j in xrange(len(myList[i])):
        newList[j][i] = myList[i][j]

print newList
dmg
  • 7,438
  • 2
  • 24
  • 33
  • This is not more perfomant than using builtins in Python 2. For the test data `[range(1000000) for i in xrange(8)]` this code executes in 3 seconds on my system while my code takes 1.8 seconds. If you don't build lists but stick with tuples instead it is done in 0.26 seconds. – filmor Mar 18 '13 at 10:08
  • @filmor You are right, I was running it with PyPy and interestingly enough somewhere around 100x1000 these turn out to be faster than `zip` (tuple or list). I could post some numbers if you want. – dmg Mar 18 '13 at 10:24
  • This is indeed interesting, seems like PyPy is optimising better than the C compiler in this case ;) – filmor Mar 19 '13 at 08:38