Zipping Arrays

August 23, 2010

When programming in any language, you are sure to be in a situation at some point where you have two or more arrays that match up by index. For example, say you have this:

cities = %w[Baltimore Washington Pittsburgh]
teams = %w[Ravens Redskins Steelers]

So the in this case, the name of the team in the nth city is the nth team. In languages like Java and JavaScript, a common method for doing this would be to use a for loop and pull each value out of the array using the index:

for i in (0...cities.size)
  puts "%s %s" % [cities[i], teams[i]]
end

As you can see, this works in Ruby as well. The output of that will be:

Baltimore Ravens
Washington Redskins
Pittsburgh Steelers

But Ruby's enumerable class has a built-in method for handling this that you might not know about. On any Enumerable, you can call zip and pass in another array and it will return a two-dimensional array with each of the values paired up:

p cities.zip(teams) 
# => [["Baltimore", "Ravens"], ["Washington", "Redskins"], ["Pittsburgh", "Steelers"]]

Conveniently, Ruby's each method also allows you to assign each value of the sub-array to a variable in the block. So we can perform the for loop from above like this:

cities.zip(teams).each do |city, team|
  puts "%s %s" % [city, team]
end

Which outputs:

Baltimore Ravens
Washington Redskins
Pittsburgh Steelers

No indexes to keep track of. Also, the zip method can take multiple arrays, so you can zip up more than one array and iterate through them in a similar fashion:

qbs = %w[Flacco McNabb Roethlisberger]

cities.zip(teams, qbs).each do |city, team, qb|
  puts "%s %s %s" % [city, team, qb]
end

Which outputs:

Baltimore Ravens Flacco
Washington Redskins McNabb
Pittsburgh Steelers Roethlisberger

Posted in Technology | Tags Ruby

Comments

1.

A super neat and useful bit of python is that you can use zip and the explode operator * to transpose a matrix:

>>> x = [[1,1],
... [0,1]]
>>> x
[[1, 1], [0, 1]]
>>> zip(*x)
[(1, 0), (1, 1)]

Though it's not useful in ruby, because [] has a transpose method, you can do the same thing:

>> x = [[1,1],[0,1]]
=> [[1, 1], [0, 1]]
>> x[0].zip *x[1..-1]
=> [[1, 0], [1, 1]]

I add it just to note an important use of zip()s in general.

# Posted By Bill Mill on Monday, August 23 2010 at 10:09 PM

2.

Nice post, Paul. Thanks.

# Posted By Scott on Tuesday, August 24 2010 at 1:22 AM

3.

Great description! The word "zip" is a bit overloaded in tech, so instead of thinking "compression", rubyists should think of a zipper on a jacket, with an array on each side. Each element is a tooth in the zipper. When the zipper is pulled up, the arrays are joined together.

# Posted By Jonathan Julian on Tuesday, August 24 2010 at 1:20 PM

Comments Disabled