Skip to content Skip to sidebar Skip to footer

Splitting A List Of Sequences Into Two Lists Efficiently

Possible Duplicate: A Transpose/Unzip Function in Python I have a list of sequences, each sequence has two items. I would like to turn this into two lists. catalog = [('abc', '1

Solution 1:

>>> catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
>>> names, vals = zip(*catalog)
>>> names
('abc', 'foo', 'bar', 'test')
>>> vals
('123', '456', '789', '1337')

The *catalog syntax here is called Unpacking Argument Lists, and zip(*catalog) translates into the call zip(catalog[0], catalog[1], catalog[2], ...).

The zip() builtin function groups iterables by indices, so when you pass a bunch of two-element tuples as above, you get a two-element list of tuples where the first tuple contains the first element of each tuple from catalog, and the second tuple contains the second element from each tuple from catalog.

In a quick timeit test the zip() version outperforms a looping approach when I tested with 1,000,000 pairs:

In [1]: catalog = [(i, i+1) for i in range(1000000)]

In [2]: def with_zip():
   ...:     return zip(*catalog)
   ...: 

In [3]: def without_zip():
   ...:     names, vals = [], []
   ...:     for name, val in catalog:
   ...:         names.append(name)
   ...:         vals.append(val)
   ...:     return names, vals
   ...: 

In [4]: %timeit with_zip()
1 loops, best of 3: 176 ms per loop

In [5]: %timeit without_zip()
1 loops, best of 3: 250 ms per loop

Solution 2:

Sure, use this:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
tup1, tup2 = zip(*lst)

The above will return a pair of tuples with the elements. If you need lists, then use this:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')]
lst1, lst2 = map(list, zip(*lst))

Post a Comment for "Splitting A List Of Sequences Into Two Lists Efficiently"