Rubyには配列を対象にした便利なメソッドが幾つもありますが、zipメソッドもそのような便利なメソッドの1つです。とはいえzipと言えばファイル圧縮の方法では、と思われる方もいるでしょう。
Rubyの配列クラスで使えるzipメソッドは、まるでジッパーを閉じるように複数のは配列を1つの配列にまとめるメソッドです。今回はこの配列を対象とするzipメソッドの機能と使い方について解説します。
配列クラスzipメソッドとは
Ruby以外のプログラム言語で配列に含まれる要素を操作しようとしたら、返し処理の中で配列の要素を加工することが多いと思います。しかしRubyには配列を操作する便利なメソッドが用意されているので、わざわざ繰り返し処理を使う必要はありません。
今回紹介するzipメソッドもそのような機能の1つです。使い方を紹介する前に、zipメソッドの基本について解説します。
配列クラスのzipメソッドの文法
配列クラスのzipメソッドは配列を対象とし、その配列と引数に渡した配列の各要素からなる配列を要素とする2次元の配列を生成します。
なお生成される配列には、対象とした配列の要素は1番目に、そして引数に指定する配列の要素を2番目以降に格納します。
配列クラスのzipメソッドの文法
2次元の配列 = 対象の配列.zip(引数の配列1, 引数の配列2, … )
生成される2次元の配列
[ [対象の配列の1番目、引数の配列1の1番目、引数の配列2の1番目…] … ]
zipメソッドの使用例
ar1 = [1, 2, 3] out = ar1.zip(["one", "two", "three"], ["un", "deux", "trois"]] p out # [[1, "one", "un"], [2, "two", "dux"], [3, "three", "trois"]]が表示される
zipメソッドでブロックを指定した場合
配列クラスのzipメソッドはブロックを指定することで、生成した配列の要素を1つずつ処理することが可能です。この場合、次のように記述します。
zipメソッドのブロックを使う方法
対象の配列.zip(引数の配列1, 引数の配列2, … ) do |配列を格納する変数|
生成した配列に対する処理
end
ブロックを利用したzipメソッドの使用例
ar1 = [1, 2, 3] out = ar1.zip(["one", "two", "three"], ["un", "deux", "trois"]] do |arr| p arr end
上記の例の実行例
[1, "one", "un"] [2, "two", "dux"] [3, "three", "trois"]
もし配列以外を指定したら
zipメソッドは配列クラスのメソッドのため、zipメソッドの対象は配列でなければなりません。さらに引数も配列を指定してください。
なお、引数に指定する配列の要素の数を、zipメソッドの対象とする配列に合わせる必要はありません。引数には空の配列も指定できます。そしてこの場合、要素の代わりにnilが代入されます。
zipメソッドで引数に空の配列を使った例
ar1 = [1, 2, 3] ar2 = ["one", "two", "three"] ar3 = [] out = ar1.zip(ar2, ar3) p out # [[1, "one", nil], [2, "two", nil], [3, "three", nil]]が表示される
なぜzip?
今回紹介するzipメソッドは、複数の配列から1つの配列をつくるメソッドですが、なぜzipと命名されたのでしょうか。
Rubyの標準で使えるメソッドの多くの名称に、そのメソッドの機能に近い英単語が採用されています。そのため、zipの意味とzipメソッドの機能を理解すると、なぜzipメソッドと命名されたを理解できます。
次からzipの意味とzipメソッドの機能について紹介します。
zipの意味
英語のzipは、元気を与える、高速で送信する、といった意味もありますが、ジッパーで締めるという意味で使われます。普段の会話でzipと言えば、ジッパーのことを差すと考えて良いでしょう。
なおIT用語でzipと言えば、gzipやWinzipなどのアプリケーションで作れるzip形式を指す言葉です。もちろんRubyでもzipファイルが扱えます。しかし、今回紹介するzipメソッドは、このzip形式とは関係ありません。
配列クラスのzipメソッドは、その処理がジッパーで締めるイメージに近いことで命名されたメソッドです。その動作を理解していれば、なぜzipを命名されたかが理解できます。
zipメソッドの処理とは
先ほどzipメソッドを複数の配列から2次元の配列を作るメソッドと紹介しましたが、それがジッパーの動作に似ていると言われても理解できないかもしれません。そこで図を使って解説します。
まず下の図を見てください。「No.」と「英語」の2つの配列を表現しています。この2つの配列をzipメソッドで1つの配列にまとめます。
上の図に紹介した2つの配列にzipメソッドを適用すると、下図のような2次元の配列を返します。
いかがでしょうか。2つに分かれていたまるでジッパーのような配列が、要素ごとにかみ合って締まったように見えませんか。このようにzipメソッドは、2つの配列のそれぞれの要素を1つのは配列に繋ぎ、それらを要素とする配列を作るメソッドです。
zipメソッドの使用例
Rubyのプログラムでは繰り返し処理の中で配列を操作する必要はありません。ほとんどのケースで、その処理専用のメソッドを利用するだけで処理できます。そして今回紹介するzipメソッドは、複数の配列を扱うケースでよく使われるメソッドです。
次に繰り返し処理をzipメソッドに置き換える使用例を紹介します。
複数の配列の要素を順番に参照する例
複数の配列の要素を処理するプログラムを作る場合、どうすればいいでしょうか。C言語など他のプログラム言語を習った方なら、繰り返し処理の中で、配列を添え字で参照するプログラムを使いがちです。
例えば、2つの配列の要素を順番に並べて表示するプログラムを作るとします。配列の添え字で呼び出すプログラムは、下記のように書けます。
繰り返しの中で配列の添え字で呼び出す例
ar1 = [1, 2, 3, 4, 5] ar2 = ["one", "two", "three", "four", "five"] i=0 limit = ar1.length while i < limit do print ar1[i], " ", ar2[i], "\n" i=i+1 end
実行結果
1 one 2 two 3 three 4 four 5 five
しかし、このプログラムはRubyらしくありません。今回紹介しているzipメソッドを使えば、もっとシンプルに記述できます。先ほど、zipメソッドでブロックが使えると紹介しましたが、ブロックの||で囲った変数を配列の数だけ設定することで、zipメソッドに指定した配列の要素を直接参照できます。
上記の例をzipメソッドで書き換えた例が次のとおりです。
zipメソッドで配列の要素を参照する例
ar1 = [1, 2, 3, 4, 5] ar2 = ["one", "two", "three", "four", "five"] ar1.zip(ar2) do |x1, x2| print x1, " ", x2, "\n" end
まとめ
これまで紹介したよう複数の配列をまるでジッパーを閉じるように1つの配列にするメソッドがzipメソッドです。zipと聞くと圧縮ファイルを扱うzip形式を連想される方が多いと思いますが、このzipメソッドは圧縮やアーカイブとは関係ありません。
Rubyでも配列の要素を添え字で参照することは可能です。しかし、添え字を使うプログラムはRubyらしくありません。zipメソッドとブロックをうまく使えば、複数の配列を参照する処理をシンプルに記述できます。
ぜひ、zipメソッドを使ってRubyらしいシンプルで読みやすいプログラムを記述できるようになりましょう。