DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป is a community of 970,177 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Efficient zip function in JavaScript
Mรกtyรกs Fodor
Mรกtyรกs Fodor

Posted on

Efficient zip function in JavaScript

Efficient zip function in JavaScript

The Python zip function is a clever analogy of a real zipper: It allows you to iterate over multiple arrays element-wise without having to worry about indices. It is quite handy when you have to manually pair elements coming from two (or more) data sources:

>>> scoreList = [5, 3, 6, 8]
>>> playerList = ['Mary', 'John', 'Emma', 'Gavin']
>>> list(zip(scoreList, playerList))
# [(5, 'Mary'), (3, 'John'), (6, 'Emma'), (8, 'Gavin')]
Enter fullscreen mode Exit fullscreen mode

Please note the list() call is needed to convert the result to a list, otherwise it returns something like

>>> zip(scoreList, playerList)
# <zip object at 0x109b19d00>
Enter fullscreen mode Exit fullscreen mode

which is an object implementing the iterator interface. Why the hassle with this object? Why is it not just a list? The iterator interface allows lazy-evaluation, meaning it won't create a list, only if it's asked. This object instead allows generating elements on-demand, which can be more efficient. Let's say I want to find the first player with score 6:

for score, player in zip(scoreList, playerList):
  if score == 6:
    print(f'player {player} has score 6')
    break
Enter fullscreen mode Exit fullscreen mode

In this case, the iteration stops with ((6, 'Emma')) and the last pair ((8, 'Gavin')) would never be constructed.

The implementation is quite interesting, because zip not only works with two lists, it can more than two arrays as input parameters. This can be particularly useful when trying to transpose a list of lists (a matrix). If you're not familiar with the term transpose, it simply means a list of list is simply flipped by its diagonal. The transposition of

[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]
Enter fullscreen mode Exit fullscreen mode

is

>>> list(zip(*[
...  [1, 2, 3],
...  [4, 5, 6],
...  [7, 8, 9]
... ]))
[
  [1, 4, 7],
  [2, 5, 8],
  [3, 6, 9]
]
Enter fullscreen mode Exit fullscreen mode

What happens if the input arrays do not have the same length? According to the Python docs it stops when the shortest input iterable is exhausted, meaning it will return as many elements as long the shortest array is:

>>> list(zip([1, 2, 3], [4, 5]))
[(1, 4), (2, 5)]
Enter fullscreen mode Exit fullscreen mode

If all elements need to be returned, itertools.zip_longest should be used.

And just to spice things up the little, let me mention that as the zip function expects iterables as input, not specifically arrays. Iterables are more generic than arrays, without going too much into the details, they are objects that can be iterated over one element at the time, and they can signal if they are exhausted (iteration finished). In practice, it means that any object that can be iterated over can be used as inputs of zip: tuples, sets, dictionaries, range, or even results of other zips. Mind-blowing, right? ๐Ÿคฏ It is also possible to create an infinite zip. Let me use itertools.count to demonstrate it. It is very similar to range() except it has no stopping criteria, so if it is used in a for loop it keeps yielding values unless it is stopped.

>>> for a, b in zip(itertools.count(start=0, step=2), itertools.count(start=1, step=2)):
...     print(a, b)
1 2
3 4
5 6
...
Enter fullscreen mode Exit fullscreen mode

I really hope I could convince you by now, how cool and versatile this Python standard library function is. Why can't we have nice things in JavaScript? Well we can, you just probably end up hunting for third-parties on npm or ready-made solutions on Stack Overflow. But is there anything more satisfying than using your home-grown utilities? You can find it out on my website.

Top comments (0)

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.