I have a list of 2-item tuples and I'd like to convert them to 2 lists where the first contains the first item in each tuple and the second list holds the second item.
original = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] # and I want to become... result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])
Is there a builtin function that does that?
zip is its own inverse! Provided you use the special * operator.
>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]) [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
The way this works is by calling
zip with the arguments:
zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
… except the arguments are passed to
zip directly (after being converted to a tuple), so there's no need to worry about the number of arguments getting too big.
You could also do
result = ([ a for a,b in original ], [ b for a,b in original ])
It should scale better. Especially if Python makes good on not expanding the list comprehensions unless needed.
(Incidentally, it makes a 2-tuple (pair) of lists, rather than a list of tuples, like
If generators instead of actual lists are ok, this would do that:
result = (( a for a,b in original ), ( b for a,b in original ))
The generators don't munch through the list until you ask for each element, but on the other hand, they do keep references to the original list.