Reputation: 19989
What is the fastest and most elegant way of doing list of lists from two lists?
I have
In [1]: a=[1,2,3,4,5,6]
In [2]: b=[7,8,9,10,11,12]
In [3]: zip(a,b)
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)]
And I'd like to have
In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
I was thinking about using map instead of zip, but I don't know if there is some standard library method to put as a first argument.
I can def my own function for this, and use map, my question is if there is already implemented something. No is also an answer.
Upvotes: 139
Views: 155927
Reputation: 1753
How about this?
>>> def list_(*args): return list(args)
>>> map(list_, range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
Or even better:
>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
Update for Python 3:
In Python 3 map returns an iterator and not a list. This is the fastest from a few options I've tested (timed using the timeit
module):
[list(t) for t in zip(*lists)]
Update for 3.12 The fastest way so far right now seems to be
[[*t] for t in zip(a, b)]
Upvotes: 7
Reputation: 5760
If you are zipping more than 2 lists (or even only 2, for that matter), a readable way would be:
[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]
This uses a list comprehension to apply list
to each element (tuple) in the list, converting them into lists.
Upvotes: 143
Reputation: 22459
The definition of elegance can be quite questionable but if you are working with numpy
the creation of an array and its conversion to list (if needed...) could be very practical even though not so efficient compared to using the map
function or the list comprehension.
import numpy as np
a = b = range(10)
zipped = zip(a,b)
# result = np.array(zipped).tolist() Python 2.7
result = np.array(list(zipped)).tolist()
Out: [[0, 0],
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5],
[6, 6],
[7, 7],
[8, 8],
[9, 9]]
Otherwise skipping the zip
function you can use directly np.dstack
:
np.dstack((a,b))[0].tolist()
Upvotes: 3
Reputation: 10062
You almost had the answer yourself. Don't use map
instead of zip
. Use map
AND zip
.
You can use map along with zip for an elegant, functional approach:
list(map(list, zip(a, b)))
zip
returns a list of tuples. map(list, [...])
calls list
on each tuple in the list. list(map([...])
turns the map object into a readable list.
Upvotes: 90
Reputation: 59
List comprehension would be very simple solution I guess.
a=[1,2,3,4,5,6]
b=[7,8,9,10,11,12]
x = [[i, j] for i, j in zip(a,b)]
print(x)
output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
Upvotes: 5
Reputation: 574
I love the elegance of the zip function, but using the itemgetter() function in the operator module appears to be much faster. I wrote a simple script to test this:
import time
from operator import itemgetter
list1 = list()
list2 = list()
origlist = list()
for i in range (1,5000000):
t = (i, 2*i)
origlist.append(t)
print "Using zip"
starttime = time.time()
list1, list2 = map(list, zip(*origlist))
elapsed = time.time()-starttime
print elapsed
print "Using itemgetter"
starttime = time.time()
list1 = map(itemgetter(0),origlist)
list2 = map(itemgetter(1),origlist)
elapsed = time.time()-starttime
print elapsed
I expected zip to be faster, but the itemgetter method wins by a long shot:
Using zip
6.1550450325
Using itemgetter
0.768098831177
Upvotes: 16
Reputation: 23073
I generally don't like using lambda, but...
>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = lambda a, b: [list(c) for c in zip(a, b)]
>>> c(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
If you need the extra speed, map is slightly faster:
>>> d = lambda a, b: map(list, zip(a, b))
>>> d(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
However, map is considered unpythonic and should only be used for performance tuning.
Upvotes: 5