◆当サイトで人気のプログラミング教室のおすすめランキングはこちら!
プログラミングは独学では非効率で、時間を無駄にするリスクがあります。効率的なカリキュラムで学べるスクールを受講しましょう。

DMM WEBCAMP【マンツーマンサポート】1ヶ月短期集中でプログラミングを学ぶスクール
1ヶ月通い放題・メンター常駐の教室環境でプログラミングを学びたい方!
TechAcademyオンラインで開講しているプログラミングスクール
オンラインでどこでも学べる!/教室に行くのが忙しい人でも安心!
TECH::CAMP教養としてのITスキルを学べるスクール
Webデザイン/AI(人工知能)/IOS/Androidアプリ制作/VRを学びたい方!
DMM WEBCAMP PRO転職保証付き!エンジニアとして転職したい人におすすめ!
未経験からプロのエンジニアへ3ヶ月で転職する為のスクールです!
1月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のDMM WEBCAMP PROコース。
12月生は満員となっております。1月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!
※プログラミングを学んでみたいけど、時間がなくて全文の記事が読めない!という方は、WebCampの無料説明会(毎日開催)に参加してみてください!

 

Rubyの繰り返し処理 each

プログラムで繰り返しを行うことはよくあることです。

ただし一般的には、単純に繰り返すだけのことは、ほとんどないでしょう。

「繰り返しの回数によって計算や処理を変える」場合や、「繰り返しの処理で得られた要素によって違った処理を行う」場合、「繰り返しで得られた結果をまとめて取得する」場合など、そのプログラムに合わせた処理を行うことがほとんどです。

もちろん、それらの処理でも、forの繰り返しをベースに作ることはできます。

しかし、forを使う場合は余計な変数を準備したり、条件分岐を作ったりする必要があり、プログラムコードが煩雑になってしまうことが少なくありません。

そこで、eachなどのメソッドの出番になります。

数種類あるメソッドを使うことで、よりシンプルに分かりやすくプログラムを作ることができるのです。

forよりももっと細かく簡単に

forは、与えられたオブジェクトの要素を1つずつ取り出しながら処理を繰り返すものです。

それ以上でもそれ以下でもありません。ただ、多数の要素が連なったオブジェクト(配列やハッシュ)の内容を1つずつ参照したり、変更したりするプログラムでは、とてもシンプルなプログラムを作ることができます。

forは配列(array)と相性が良い

forがどれくらい配列と相性が良いのか、具体的に見ていきましょう。

例えば、長さの分からないある配列、q_arrayがあったとして、この配列に入っている値を表示してみたいとします。

もしfor以外の繰り返しとしては、while(詳しくは「【Ruby入門説明書】繰り返し、whileについて解説」を参照してください)があります。まずは、それらで実装してみましょう。

each00-1.rb

len = ARGV.length
i = 0

while i < len do
  puts ARGV[i]
  i += 1
end

入力される配列は長さが分からないということですので、コマンド引数ARGVを利用して表現しています(ARGVについては、「【Ruby入門説明書】ruby unlessについて解説」にて紹介しています)。

上記のプログラムを実行するときに、任意の数の値を渡すことができますので、プログラムを作っている段階では長さが分からない配列になるわけです。
では、上記のプログラムeach00-1.rbを、以下のようにして実行してみましょう。

ruby each00-1.rb aa bb cc dd

もちろん、「aa bb cc dd」の部分は、半角の空白で区切った文字をいくつ追加しても、なしでもかまいません。そうして実行すると、引数で渡した文字が縦にずらっと並ぶことが分かると思います。

(結果)

aa
bb
cc
dd

上述のように、whileでも配列から要素を1つずつ取り出して処理することは難しくありません。

しかし、forのプログラムを見れば、その簡単さに驚くでしょう。

each00-2.rb

for ar in ARGV
  puts ar
end

同じように起動してみれば、each00-1.rbと同様の動きをすることが確認できます。forは余計な処理をまったく行うことなく、forが配列の中身を直接取得して表示することができるわけです。

しかし、残念ながらforでも少し面倒なことがあります。

forより相性が良い「each」

forは配列と相性が良いといっても、その動きは「配列の要素を1つずつ取り出す」ことです。

じつは、まったく同じことができるメソッドが存在し、そちらはより配列と相性が良いのです。

それが、eachメソッドです。

eachで繰り返す場合の構文は、以下のようになります。

オブジェクト.each do |変数|
  処理
end

each00-2.rbと同じプログラムを、eachを使って作ってみましょう。

each01-1.rb

ARGV.each do |ar|
  puts ar
end

forと同じく非常にシンプルですね。

eachは配列オブジェクトのメソッドですので、配列と相性が良いのは当たり前ですが、ここまでforと似ていると、少し使いどころが分からないかもしれません。

eachは確かにforとまったく同じことができます。しかし、forよりももっときめ細かな処理を行うことができる優れものを率いているのです。

じつは、forは、内部的にeachを使っています。forはeachの繰り返し部分を特化させて分かりやすくしたものだと考えれば良いかもしれません。(何でもできるコンピュータよりも、映像を見ることしかできないTVのほうが迷わず使えるものです)

do~endと{~}

ここで、少しだけ文法から離れてRubyの記載方法について、説明しておきます。

ここまで紹介したeachについては、繰り返す処理をdoとendで囲んでいます。

このdoとendで囲まれている部分を、ブロックと呼び、繰り返す処理を明確にする役割があります。

ただ、このブロックをdoとendで囲むという方法は、少し煩雑で見にくくなってしまうことがあります。

そのため、doとendで囲む代わりに、{と}で囲む方法でも良いことになっています。例えば、すぐ上のeach01-1.rbのプログラムは、以下のように書いても問題ありません。

each01-2.rb

ARGV.each { |ar|
  puts ar
}

必ず{~}を使わなければいけないわけではありませんが、C言語などの他のプログラムから入ってきた人は、この{~}で囲むやり方はなじみがあり、多くのサンプルで使われていますので、知っておいたほうが良いでしょう。

時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】

eachの派生でいろいろできる

では、eachが率いている力強い仲間たちを紹介していきましょう。

each_with_index

繰り返しの処理を行う中で、時々必要になるのが、いま取り出した要素が変数が何番目の要素なのかということです。

例えば、each01.rbで、表示されている文字列が何番目に入力されたのかを知りたい場合、eachを使えば次のようになります。

each02-1.rb

i = 1

ARGV.each do |ar|
  print( i, ":", ar, "\n")
  i += 1
end

(結果)

1:aa
2:bb
3:cc
4:dd

変数iで要素番号を数えて表示していますので、少し煩雑ですね。そこで、eachの派生である「each_with_index」の出番です。

ちなみに、「each_with_index」の文法は、以下のようになっています。

オブジェクト.each_with_index do |要素用の変数, インデックス用の変数|
  処理
end

「each_with_index」を使ってeach02-1.rbと同じものを作った場合、次のようになります。

each02-2.rb

ARGV.each_with_index do |ar,i|
  print( i + 1, ":", ar, "\n")
end

要素番号も繰り返しの中で一緒に取得できるようになっているので、とてもシンプルですね。

しかし、じつはeach02-2.rbは、表示されているインデックスが0から表示されるという残念な部分があります。そのため、printの中で「i + 1」となっています。

each.with_index

前述のインデックスについて気になるのであれば、「each.with_index」を使いましょう。

パット見たところ同じように見えますが、withの前が「.」か「_」で違いますので、注意してください。

「each.with_index」の構文は次のようになっています。

オブジェクト.each.with_index(インデックスの初期値) do |要素用の変数, インデックス用の変数|
  処理
end

each02-2.rbを、「each.with_index」を使って書き換えましょう。

each02-3.rb

ARGV.each.with_index(1) do |ar,i|
  print( i, ":", ar, "\n")
end

これで、すっきりしたプログラムになりました。
※もちろん、プログラムの他の部分との兼ね合いや好みの問題で、each02-2.rbのほうがベターな場合も少なくありません。

each_line

ここから、少し毛色が違ったメソッドです。

「each_line」は、改行を含む文字列を改行ごとに切り取って、行数分だけ処理を繰り返すメソッドです。

構文は以下です。

オブジェクト.each_line do |変数|
  処理
end

前述のとおり、オブジェクトは文字列です。

具体的なプログラムを見て、動きを確認しましょう。

each03.rb

str = "test1\ntest2\ntest3\ntest4\n"
puts str
puts
str.each_line do |s|
  puts "Ruby-" + s
end

※「\n」は改行を表す文字列です

each03.rbを実行すると、以下のように、まず文字列strをそのまま表示し、その後1行ずつ"Ruby-"を追加した文字列を表示します。
(結果)

test1
test2
test3
test4

Ruby-test1
Ruby-test2
Ruby-test3
Ruby-test4

これだけでは、わざわざこんなメソッドが存在する理由が分からないかもしれません。

今後、学習を進めていく上で、テキストファイルを扱うようになれば、このメソッドの力強さに気がつくことと思います。楽しみにしておいてください。

each_slice

このメソッドは、文字列ではなく配列や範囲を操作するのに使います。

構文は以下のようになっており、渡されたオブジェクト(配列か範囲)を要素数ごとに分割して変数に格納するメソッドです。

オブジェクト.each_slice(要素数) do |変数|
  処理
end

こちらも、具体的なプログラムを作って、動きを確認してみましょう。

each03.rb

str = [1,2,3,4,5,6,7,8,9,10,11]
print(str)
puts
str.each_slice(4) do |s|
  print(s)
end

11個の要素がある配列を4つずつ分割していくプログラムです。

以下の結果を見れば分かるように、足らなければある分だけの配列を変数へ格納しています。

(結果)

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[1, 2, 3, 4][5, 6, 7, 8][9, 10, 11]

※1行目がもとの配列をそのまま表示し、2行目がeach_slice(4)で分割された結果です

配列などのデータを扱うときに重宝するのですが、こちらも、いまの段階でこのプログラムだけを見てもピンとこないかもしれません。

将来的に活用する日は必ずありますので、そのときに改めて復習しても良いかもしれません。

存在だけはしっかりと憶えておいてください。

each_with_object

最後に紹介する「each_with_object」は、いかにもRubyらしい動きをするメソッドです。

まずは、構文を紹介します。

オブジェクト.each_with_object(引数オブジェクト) do |要素が入る変数、引数オブジェクトが入る変数|
  処理
end

「each_with_object」は、オブジェクトの要素と、操作対象となる引数オブジェクトを繰り返しの中で扱えるようにしているメソッドです。

オブジェクトの要素を使って、引数オブジェクトを操作するといったプログラムに使えます。

具体的なプログラムを見て、動きを確認してみてください。

以下のeach04.rbは、animalsという動物名のリストから、pが含まれている動物名だけを探し出して、p_aniという配列に格納(push)するプログラムです。

each04-1.rb

animals = ["dog", "cat", "mouse", "pig", "duck", "parrot"]
p_ani = []

animals.each_with_object(p_ani) do |animal, arr|
  arr.push(animal) if animal.include?("p")
end

puts p_ani

※include?()は、特定の文字列が含まれているかどうかを確認するメソッドです

(結果)

pig
parrot

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】

他にもある繰り返しメソッド「map」「select」

ここまでに紹介したメソッドは、あくまでも繰り返しの中で処理をして、その処理結果は、別途、変数などへ代入して表示していました。

しかし、じつのところ、直接結果を返してくれるものもあるのです。(メソッドは入力に対する出力をするのが基本動作なので、何かを返してくれるのは当たり前かもしれません)

例えば、すぐ上で紹介している「each_with_object」がそうです。

each04.rbを少し修正して、p_aniを事前に準備するのではなく、結果を代入するような形に変更してみましょう。

each04-2.rb

animals = ["dog", "cat", "mouse", "pig", "duck", "parrot"]

puts animals.each_with_object([]) { |animal, arr| arr.push(animal) if animal.include?("p") }

p_ani変数を使わず、繰り返しの構文をそのままputsで表示しているので、違和感を覚えるかもしれません。
(※繰り返し構文部分は改行されていてもかまいません。ここでは、敢えて1行表記しています)

しかし、これこそRubyらしいプログラムコードとも呼べますので、しっかりと憶えておきましょう。

同様に、繰り返しのメソッドから返される値を活用する繰り返しメソッドが他にもありますので、紹介しておきます。

まとめて返す「map」

mapメソッドは、eachと同じく繰り返しの処理を行うメソッドで、eachと同じ構文です。

オブジェクト.map do |変数|
  処理
end

しかし、mapは、処理の結果をまとめた配列を作って、それを返してくれるところが、eachと違っています。

例えば、ある配列[1, 2, 3, 4]のすべての要素を2倍したいようなときに、とても重宝します。

この要望をeachで実現しようとした場合は、以下のようになります。

each05-1.rb

arr = [1, 2, 3, 4]
ret = []

arr.each { |ar| ret.push(ar * 2) }
print ret

※敢えて1行で表記しています

(結果)

[2, 4, 6, 8]

まったく同じプログラムが、mapを使うと以下のようになります。

each05-2.rb

arr = [1, 2, 3, 4]
print arr.map { |ar| ar * 2 }

mapを使うことで、とてもシンプルに表現できますね。

必要なものだけまとめて返す「select」

selectは、処理をするのではなく選別する(条件に合致したデータだけ取得する)ために使用します。

構文は、以下のようになっており、eachやmapで「処理」が入るところに、「条件」が入ります。

オブジェクト.map do |変数|
  条件
end

例えば、上と同じ配列[1, 2, 3, 4]から、偶数だけ取得した配列を作りたい場合は、以下のようになります。

each06.rb

arr = [1, 2, 3, 4]
print arr.select { |ar| ar % 2 == 0 }

(結果)

[2, 4]

さて、この同じ結果が出るようなプログラムを、eachを使って作成できるでしょうか?

挑戦してみてください。

回答

arr = [1, 2, 3, 4]
ret = []

arr.each { |ar| ret.push(ar) if ar % 2 == 0 }
print ret

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー

まとめ

繰り返し処理の中でも、Rubyらしいといえるメソッドたちについて、説明しました。

ここまでの説明で、「どこで使う?」と思われた人もいるかもしれません。しかし、わざわざメソッドが準備されているくらいですので、意外にこれらのメソッドを使えるシーンは多いものです。

ぜひ、これらのメソッドを使いこなして、Ruby中級者を目指しましょう。

・forはeachの簡易版。ただ繰り返したいときにはforがシンプル
・繰り返しの制御や結果を柔軟に取得したければ、eachとその派生メソッドを使う
・eachのdo~endは{~}と書いても良い
・eachはオブジェクトの参照やオブジェクトを利用した繰り返し処理
・each_with_index、each.with_index()で、処理している要素の位置(インデックス)が分かる
・each_linは、改行を含む文字列を1行ずつ処理できる
・each_sliceは、配列や範囲を分割できる
・each_with_objectを使えば、特定のオブジェクトに対する繰り返し処理をシンプルに記載できる
・mapは繰り返し処理の結果を配列にまとめてくれる
・selectは、配列の中から条件にあった要素だけの配列を取り出せる

DMM WEBCAMP ONLINE/プログラミングコースについて

WEBCAMPでは、「どこでも学べる」オンラインコースを開講しています。

初心者・未経験の方でもわずか1ヶ月でプログラミングの基礎を学び、アプリケーション開発をすることができます。

DMM WEBCAMP ONLINEが選ばれる3つの理由

1.学習の仕方がわからなくても安心!初心者に寄り添った学習カリキュラム

これから学習を始める初心者の方や、独学で挫折してしまった方に向けて、アプリケーション作成をゴールとする一気通貫したカリキュラムを提供しています。2500名を輩出しているWebCampだからこその教室でのリアルな受講生の声を反映し、オンラインコースでも初心者に寄り添った学習体験をご提供いたします。

2.つまずいたらすぐ解決!プロのエンジニアに質問し放題

プログラミング学習で挫折する理由の多くは「つまずいた時に聞ける人がいない」ことです。オンラインコースでは、現役エンジニアやプロ講師に、すぐにチャットでの質問が可能です。つまずきをすぐに解消できるので、挫折せずに学習を継続することができます

3.1ヶ月間で終わらなくても大丈夫!カリキュラムは"卒業後"も"無料"で利用可能

受講したいけど、仕事が急に忙しくなるかもしれないから受講するか迷っている・・・そんな方も多いのではないでしょうか?ご安心ください。カリキュラムは期間終了後も「無料」で使うことができます。また、しっかり学習時間を確保した方も、振り返って学習することでプログラミングスキルがご自身に馴染んできます。

▼まずは無料でWEBデザインのカリキュラムを体験しよう!

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

おすすめの記事