Reputation: 3464
so I have this list in python,
a= [[1,2,3,4],
[2,4,5,1],
[3,4,6,2],
[2,3,4,5]]
and want to turn the list reading horizontally to vertically.
b= [[1,2,3,2],
[2,4,4,3],
[3,5,6,4],
[4,1,2,5]]
what is the best way to do it, and most efficient way to do it? i'm pretty new to programming, sorry for being noob. thanks.
Upvotes: 3
Views: 210
Reputation: 29416
Check out numpy library. You can put your list into an array and transpose it like this:
a = array ([[1,2,3,4],
[2,4,5,1],
[3,4,6,2],
[2,3,4,5]])
a.transpose()
P.S.: Explanation of Tadeck's solution is very easy. zip
has the following signature:
zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]
So, it takes a number of sequences (we don't know how much exactly) and then builds tuples in the following order: takes first element of every sequence ant puts them in the tuple, then takes second element of every sequence and puts them in the second tuple and so on. It returns list of all tuples it build during its execution.
*lst
- is, in fact, unpacking of arguments list. You can read more about it in the following note.
I hope, now everyone understands how this pretty piece of code works. :)
Upvotes: 8
Reputation: 8365
You asked about efficiency. You can use timeit for that.
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]" "zip(*a)"
1000000 loops, best of 3: 0.569 usec per loop
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]" "map(None, *a)"
1000000 loops, best of 3: 0.644 usec per loop
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]" "[[row[i] for row in a] for i in xrange(len(a[0]))]"
1000000 loops, best of 3: 1.43 usec per loop
>python -m timeit -s "from numpy import array; a = array([[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]])" "a.transpose()"
1000000 loops, best of 3: 0.249 usec per loop
For a large data set of [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]*1000000
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]*1000000" "zip(*a)"
10 loops, best of 3: 400 msec per loop
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]*1000000" "map(None, *a)"
10 loops, best of 3: 458 msec per loop
>python -m timeit -s "a = [[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]*1000000" "[[row[i] for row in a] for i in xrange(len(a[0]))]"
10 loops, best of 3: 770 msec per loop
>python -m timeit -s "from numpy import array; a = array([[1,2,3,4],[2,4,5,1],[3,4,6,2],[2,3,4,5]]*1000000)" "a.transpose()"
1000000 loops, best of 3: 0.251 usec per loop
If your lists are of different lengths, zip
truncates to the shortest length. You can use 'map' or itertools.izip_longest
to instead fill the missing values with None
.
Upvotes: 5
Reputation: 13356
Another way is:
a= [[1,2,3,4],
[2,4,5,1],
[3,4,6,2],
[2,3,4,5]]
a = [[row[i] for row in a] for i in range(len(a[0]))]
Upvotes: 1
Reputation: 137320
You can do it like that:
zip(*your_list)
Proof:
>>> a = [[1, 2, 3, 4], [2, 4, 5, 1], [3, 4, 6, 2], [2, 3, 4, 5]]
>>> zip(*a)
[(1, 2, 3, 2), (2, 4, 4, 3), (3, 5, 6, 4), (4, 1, 2, 5)]
Upvotes: 10