How to Unzip a List of Tuples into Individual Lists

How to unzip a list of tuples into individual lists?

Use zip(*list):

>>> l = [(1,2), (3,4), (8,9)]
>>> list(zip(*l))
[(1, 3, 8), (2, 4, 9)]

The zip() function pairs up the elements from all inputs, starting with the first values, then the second, etc. By using *l you apply all tuples in l as separate arguments to the zip() function, so zip() pairs up 1 with 3 with 8 first, then 2 with 4 and 9. Those happen to correspond nicely with the columns, or the transposition of l.

zip() produces tuples; if you must have mutable list objects, just map() the tuples to lists or use a list comprehension to produce a list of lists:

map(list, zip(*l))          # keep it a generator
[list(t) for t in zip(*l)] # consume the zip generator into a list of lists

Unpacking a list / tuple of pairs into two lists / tuples

>>> source_list = [('1','a'),('2','b'),('3','c'),('4','d')]
>>> list1, list2 = zip(*source_list)
>>> list1
('1', '2', '3', '4')
>>> list2
('a', 'b', 'c', 'd')

Edit: Note that zip(*iterable) is its own inverse:

>>> list(source_list) == zip(*zip(*source_list))
True

When unpacking into two lists, this becomes:

>>> list1, list2 = zip(*source_list)
>>> list(source_list) == zip(list1, list2)
True

Addition suggested by rocksportrocker.

unzip list of tuples into numpy arrays

Your list of tuples can be converted into a 2-d numpy array by calling np.array. This can then be transposed and then unpacked along the first dimension using tuple assignment:

b, c = np.array(a).T

Here this gives:

>>> import numpy as np
>>> a = [(1,2), (3,4)]
>>> b, c = np.array(a).T # or: np.array(a).transpose()
>>> b
array([1, 3])
>>> c
array([2, 4])

Caveat: you will have a temporary array with the same number of elements as a, so it might be less memory-efficient than your original solution, particularly if you are unpacking into a larger number of 1d arrays.

Transpose/Unzip Function (inverse of zip)?

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.

python3 unzipping a list of tuples

Python 2:

Python 2.7.6 (default, Apr  9 2014, 11:48:52) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> di={'word1':22, 'word2':45, 'word3':66}
>>> zip(*sorted(di.items(), key=itemgetter(1), reverse=True))
[('word3', 'word2', 'word1'), (66, 45, 22)]
>>> k,v=zip(*sorted(di.items(), key=itemgetter(1), reverse=True))
>>> k
('word3', 'word2', 'word1')
>>> v
(66, 45, 22)

Python 3:

Python 3.4.1 (default, May 19 2014, 13:10:29) 
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> di={'word1':22, 'word2':45, 'word3':66}
>>> k,v=zip(*sorted(di.items(), key=itemgetter(1), reverse=True))
>>> k
('word3', 'word2', 'word1')
>>> v
(66, 45, 22)

It is exactly the same for both Python 2 and Python 3

If you want lists vs tuples (both Python 3 and Python 2):

>>> k,v=map(list, zip(*sorted(di.items(), key=itemgetter(1), reverse=True)))
>>> k
['word3', 'word2', 'word1']
>>> v
[66, 45, 22]

How to unpack single-item tuples in a list of lists

You need nested comprehensions (with either a two layer loop in the inner comprehension, or use chain.from_iterable for flattening). Example with two layer loop (avoids need for imports), see the linked question for other ways to flatten the inner list of tuples:

>>> listolists = [[('1st',), ('2nd',), ('5th',)], [('1st',)]]
>>> [[x for tup in lst for x in tup] for lst in listolists]
[['1st', '2nd', '5th'], ['1st']]

Note that in this specific case of single element tuples, you can avoid the more complicated flattening with just:

 >>> [[x for x, in lst] for lst in listolists]

per the safest way of getting the only element from a single-element sequence in Python.

What's an elegant way to extract a series of entries in a list of tuples into sublists?

You can use tuple() function to transform lists into tuples, so you will be able to append all of the tuples inside listOfTuples variable into the output that you need:

TRUE = 1
lot = [('selectable', 'frequency'), ('color', 'green'), ('item', '10 Hz'),
('value', 10), ('align', 'left'), ('hidden', TRUE), ('item', '20 Hz'),
('value', 20), ('align', 'right'), ('item', '50 Hz'), ('value', 50),
('item', '100 Hz'), ('value', 100), ('textColor', 0xFF0000)]

l = [[]]
for i in lot:
if i[0]=='item':
l[-1] = tuple(l[-1])
l.append([])
l[-1].append(i)
print(l[1:])

Output:

[(('item', '10 Hz'), ('value', 10), ('align', 'left'), ('hidden', 1)), (('item', '20 Hz'), ('value', 20), ('align', 'right')), (('item', '50 Hz'), ('value', 50)), [('item', '100 Hz'), ('value', 100), ('textColor', 16711680)]]

The only disadvantage of this method is that you need to remove the first element of the output list of tuples, so it may doesn't work in certain situations.

How to convert list of tuples to multiple lists?

The built-in function zip() will almost do what you want:

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

The only difference is that you get tuples instead of lists. You can convert them to lists using

list(map(list, zip(*[(1, 2), (3, 4), (5, 6)])))


Related Topics



Leave a reply



Submit