What Is the Inverse Function of Zip in Python

What is the inverse function of zip in python?

lst1, lst2 = zip(*zipped_list)

should give you the unzipped list.

*zipped_list unpacks the zipped_list object. it then passes all the tuples from the zipped_list object to zip, which just packs them back up as they were when you passed them in.

so if:

a = [1,2,3]
b = [4,5,6]

then zipped_list = zip(a,b) gives you:

[(1,4), (2,5), (3,6)]

and *zipped_list gives you back

(1,4), (2,5), (3,6)

zipping that with zip(*zipped_list) gives you back the two collections:

[(1, 2, 3), (4, 5, 6)]

Transpose/Unzip Function (inverse of zip)?

In 2.x, 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)]

This is equivalent to calling zip with each element of the list as a separate argument:

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.

In 3.x, zip returns a lazy iterator, but this is trivially converted:

>>> list(zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)]))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

zip inverse function in Python - Nested list having different length of sublist

zip() stops when one of the sequences runs out, i.e. it only returns only as many items as the smallest sub sequences has elements.

The returned list is truncated in length to the length of the shortest argument sequence

itertools have izip_longest(), which runs over the longest sequences, returning a filler element for non-existing items:

>>> a = [[1,2],[1]]
>>> from itertools import izip_longest
>>> print list(izip_longest(*a))
[(1, 1), (2, None)]

What is the inverse function of itertools.izip in python?

What's wrong with a traditional loop?

>>> def gen():
... yield 'first', 0, 1
... yield 'second', 2, 3
... yield 'third', 4, 5
...
>>> numbers = []
>>> for data, num1, num2 in gen():
... print data
... numbers.append((num1, num2))
...
first
second
third
>>> numbers
[(0, 1), (2, 3), (4, 5)]

Python: why is zip(*) used instead of unzip()?

You're not actually unzipping when you do zip(*your_list). You're still zipping.

zip is a function that can take as many arguments as you want. In your case, you essentially have four different sequences that you want to zip: ('a', 1), ('b', 2), ('c', 3) and ('d', 4). Thus, you want to call zip like this:

>>> zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

But your sequences aren't in separate variables, you just have a list which contains them all. This is where the * operator comes in. This operator unpacks the list in a way that each element of your list becomes an argument to the function.

This means that when you do this:

your_list = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
zip(*your_list)

Python calls zip which each element of your list as an argument, like this:

zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))

This is why an unzip function isn't necessary: Unzipping is just another kind of zip, and is easily achievable with just the zip function and the * operator.

Python zip list of tuples

Just use zip and list comprehension.

>>> tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [list(i) for i in zip(*tuples)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Or,

>>> tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [[*i] for i in zip(*tuples)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Iterate a Python zip list and save the result in two different lists

Assuming you want the sums in one list and the differences in another, there isn't a straightforward way to do that with a list comprehension. You could collect the pairs in a tuple and then split back up into two lists:

tup = [(compute_add(x, y), compute_sub(x, y)) for x, y in zip(list1, list2)]
res1 = [t[0] for t in tup]
res2 = [t[1] for t in tup]

With just a single loop over the zip, I would simply do

res1 = []
res2 = []
for x, y in zip(list1, list2):
res1.append(compute_add(x,y))
res2.append(compute_sub(x,y))

If the functions are genuinely this simple, of course, you can factor out the multiplication:

for x, y in zip(list1, list2):
mul = x * y
res1.append(mul + 10)
res2.append(mul - 10)

For what it's worth, What is the inverse function of zip in python? has a nice answer to "how can I do the reverse of zip()" but it effectively traverses the list two times as well.

Zip lists in Python

When you zip() together three lists containing 20 elements each, the result has twenty elements. Each element is a three-tuple.

See for yourself:

In [1]: a = b = c = range(20)

In [2]: zip(a, b, c)
Out[2]:
[(0, 0, 0),
(1, 1, 1),
...
(17, 17, 17),
(18, 18, 18),
(19, 19, 19)]

To find out how many elements each tuple contains, you could examine the length of the first element:

In [3]: result = zip(a, b, c)

In [4]: len(result[0])
Out[4]: 3

Of course, this won't work if the lists were empty to start with.

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


Related Topics



Leave a reply



Submit