【Ruby eachの応用編】さまざまな使い方を網羅的に理解しよう

Rubyのeachメソッドで配列やハッシュの処理を行いたい
配列やハッシュの要素を順番に処理する方法が知りたい
eachメソッドってよく見かけるけどどうやって使うの?

eachメソッドを使用すれば配列やハッシュの要素を順番に取り出すことができます。また、関連したメソッドを使用すれば、さまざまな処理を行うことができます。

たとえば、配列の要素ごとに順番にブロックで処理を行ったり、処理を分岐させるといったことも可能になります。つまり、eachメソッドを使い方こなせば、配列やハッシュから自由に値を取り出すことができるのです。

実際のプログラムでもeachを使った処理は使用頻度が高いので、しっかりマスターするようにしましょう。

この記事では、配列のeachの使い方について以下の内容で解説していきます。

  • eachとは?
  • 配列でのeachメソッドの扱い方
  • ハッシュでのeachメソッドの使い方

目次

Rubyのeachとは

eachとは、配列においてもっとも基本的なメソッドです。

eachメソッドを使うことによって、配列に含まれる要素を順番にプロックに渡して、簡単に任意の処理をすることができます。

eachメソッドの基礎については、以下の記事で詳しく解説しています。

さまざまなeachメソッド

eachは先述したように配列の値を要素ごとに取り出すことができます。

では実際にeachを使ってみましょう。

サンプルコード:

array = [10,20,30]

array.each do |a|
  p a
end

サンプルコードの実行結果:

10
20
30

eachは「配列.each{|変数|〜}」で指定した変数に配列の要素を1つずつ取り出して処理を実行します。このように、配列の要素である10,20,30が順番にブロックに渡されていることがわかります.

each_with_index(インデックス番号を扱う)

さきほど、説明したeachメソッドだけではインデックス番号をブロックの中で扱うことができません。もし、インデックス番号もブロックで扱いたいときはeach_with_indexという便利なメソッドが用意されています。

サンプルコード:

array = [10,20,30]

array.each_with_index do |a,i|
  p "#{i}番目の配列の要素は#{a}です。"
end

サンプルコードの実行結果:

"0番目の配列の要素は10です。"
"1番目の配列の要素は20です。"
"2番目の配列の要素は30です。"

一番初めのaには、配列の要素が代入され、二番目のiにはインデックス番号が代入されています。ですが、お気づきの通りこのままでは、一番初めの要素の場合、インデックス番号が「0」なので0番目の要素になってしまいます。

そのため、1番目の要素と表示したい場合は下記のメソッドを使用します。

each.with_index(初期値を設定して、インデックス番号を扱う)

each.with_indexメソッドでは、始めに初期値をインデック番号に設定することができます。each_with_indexでは0番目の要素表示されてしまった部分を修正することができます。

サンプルコード:

array = [10,20,30]

array.each.with_index(1) do |a,i|
  p "#{i}番目の配列の要素は#{a}です。"
end

サンプルコードの実行結果:

"1番目の配列の要素は10です。"
"2番目の配列の要素は20です。"
"3番目の配列の要素は30です。"

(1)のように、カッコ内に任意の数値を初期値として設定することができます。each_with_indexメソッドとeach.with_indexメソッドは「_」と「.」が違うだけなので、覚えやすく、使い勝手もいいのでまとめて覚えてしまうことをおすすめします。

each_slice(配列の要素を指定した数値で切り分ける)

each_sliceメソッドを使えば、配列の要素を指定した数値にしたがって分割することができます。

サンプルコード:

array = [10,20,30,40,50,60]

array.each_slice(2) do |a|
  p a 
end

array.each_slice(3) do |a|
  p a 
end

サンプルコードの実行結果:

[10, 20]
[30, 40]
[50, 60]

[10, 20, 30]
[40, 50, 60]

このように、2つずつに分割したいときは2を指定して、3つずつに分割したいときは3を指定します。とても直感的ですね。

each_line(改行ごとに切り分ける)

each_lineメソッドは指定した文字列の中から改行コードで分割して1行ずつ取得する場合に使用します。

サンプルコード:

fruits = "applenorangernmelonrnpineapple"
fruits.each_line {|line| p line.chomp }

サンプルコードの実行結果:

“apple”
"orange"
"melon"
"pineapple"

このように改行コードごとに文字列が分割されていることがわかりますね!

ハッシュでのeach

ハッシュの扱い方

ハッシュとは、keyとvalueのペアを使うことで、複数オブジェクトへの参照を管理することが出来るオブジェクトです。keyは配列でのインデックス(各要素に振り分けられた番号)に相当します。

ハッシュの場合は、インデックスとは違い、keyとしてオブジェクトを指定し、たとえば下記のように、

 h = { "abc" => 1, "def" => 2 }
 h["abc"]

と指定することで、値を取得できます。ハッシュのkeyには、任意のオブジェクトを指定できます。

keys(ハッシュのkeyを配列で取得する)

ここではハッシュからkeyを取得してみましょう。

ハッシュの各要素(keyとvalueのペア)から、keysメソッドで、keyのみを配列として取り出すことが可能です。keyを配列として取り出しても、ハッシュ自体は何の影響も受けません。

取り出したkeyは、単なる配列ですので、自由に編集・操作可能です。

サンプルコード:

h = { "abc" => 1, "def" => 2, "ghi" => 3 }
k = h.keys
p k

サンプルコードの実行結果:

["abc", "def", "ghi"]

以上のように、keyを配列で取得できました。

values(ハッシュのvalueを配列で取得する)

同様にvalueも取り出すことができます。

サンプルコード:

h = { "abc" => 1, "def" => 2, "ghi" => 3 }
k = h.values
p k

サンプルコードの実行結果:

[1, 2, 3]

以上のように、valueを配列で取得できました。

foreachのようなeach (ブロックにハッシュのキーと値を繰り返し渡す)

hash = { Samurai: 1, Ruby: 2, Rails: 3 , Swift: 4, Java: 5, PHP: 6}
hash.each { |key, value| puts "#{key} => #{value}"}

サンプルコードの実行結果:

Samurai => 1
Ruby => 2
Rails => 3
Swift => 4
Java => 5
PHP => 6

このように、keyとvalueを同時に取り出すこともできます。厳密にはforeachはrubyにはありませんが、rubyで表現しようとするとこのようになります。

each_key(ブロックにハッシュのキーだけ繰り返し渡す)

配列のeachメソッドのように、ハッシュもeach_keyメソッドでループできます。配列とeachメソッド同じようにeach_keyもブロック付きメソッドですので、通常、ブロックを引数に与えます。

そのブロックのブロック引数でハッシュのkeyを取得できます。

サンプルコード:

hash = { Samurai: 1, Ruby: 2, Rails: 3 , Swift: 4, Java: 5, PHP: 6}
hash.each_key {|key|  puts "#{key}" }

サンプルコードの実行結果:

Samurai
Ruby
Rails
Swift
Java
PHP

以上のように、each_keyにより、ハッシュをkeyでループできました。ブロック内では、ブロック変数としてkeyを取得できました。

each_value(ブロックにハッシュの値だけ繰り返し渡す)

同様に、valueも取り出せます。

サンプルコード:

hash = { Samurai: 1, Ruby: 2, Rails: 3 , Swift: 4, Java: 5, PHP: 6}
hash.each_value { |value| puts "#{value}"}

サンプルコードの実行結果:

1
2
3
4
5
6

each_with_object (ブロックに値を渡して新たな配列を作成)

サンプルコード:

hash = { Samurai: 1, Ruby: 2, Rails: 3 , Swift: 4, Java: 5, PHP: 6}
picked = hash.each_with_object([]) do |(key, value), array_new|
 array_new << key if value >= 4
end
puts picked

サンプルコードの実行結果:

Swift
Java
PHP

この場合は、valueが4以上のペアのkeyを出力してします。このように、each_with_objectを使えば条件を指定してハッシュから新たな配列を作成できます。

sort (ハッシュをkeyでソートする)

ハッシュが下記のような順番であったとしましょう。

h = { "def" => 1, "ghi" => 2, "abc" => 3 }

ハッシュhのkeyはアルファベット順に並んでいません。このままeach_keyでループしてしまうと、

  1. def
  2. ghi
  3. abc

の順番でループしてしまいます。

それでは困る際に、ハッシュをkeyでソートすることができます。なおRubu1.9以上からは、ハッシュのソート結果はハッシュではなく、Enumerableになります。

サンプルコード:

h = { "def" => 1, "ghi" => 2, "abc" => 3 }
p h.sort
p h

サンプルコードの実行結果:

[["abc", 3], ["def", 1], ["ghi", 2]]
{"def"=>1, "ghi"=>2, "abc"=>3}

以上のように、sortメソッドを使用するとメソッドの戻値が、keyでソートされたEnumerableになります。Enumerableとは、配列と同等の動作をするモジュールのことです。
通常は配列と思っていただいてかまいません。

sortメソッドの戻値のEnumerableは、ハッシュの各要素を、配列[ key, value ] という要素として持っている配列です。また、sortメソッドを適用したレシーバのハッシュh自体はソートされないことも確認できました。

has_key (ハッシュにkeyが存在するか確かめる)

ハッシュから値を取り出すには、keyを指定する必要があります。しかし、ハッシュ内に存在しないkeyを指定すると、nil値が返ってきます。

そのため、事前にkeyが存在するかどうかを確認するhas_key?メソッドがあります。このメソッドにより、事前にkeyが存在するかどうかをチェックし、keyが存在する場合と、keyが存在しない場合で処理を分けることができます。

サンプルコード:

h = { "abc" => 1, "def" => 2, "ghi" => 3 }
if h.has_key? "xyz" then
  p "h has key xyz"
else
  p "h dose not have key xyz"
end

サンプルコードの実行結果:

"h dose not have key xyz"

以上のように、has_key?メソッドにkeyの候補を引数として与えることにより、レシーバのハッシュがkeyの候補を持っているかどうかをチェックできました。

has_value (ハッシュにvalueが存在するか確かめる)

同様に、valueの存在も確かめることができます。

サンプルコード:

h = { "abc" => 1, "def" => 2, "ghi" => 3 }
if h.has_value? 4 then
  p "h has value xyz"
else
  p "h dose not have value 4"
end

サンプルコードの実行結果:

"h dose not have value 4"

まとめ

この記事では、配列やハッシュにおけるeachの使い方を解説しました。

  • eachとは?
  • 配列でのeachメソッドの扱い方
  • ハッシュでのeachメソッドの使い方

eachメソッドは、その派生メソッド含めて使用の頻度が高いので、早いうちに身につけておくべきです。たくさんメソットがあるように見えますが、基本的には配列や、ハッシュの要素を順番にブロックに渡してなにかしらの処理を加えているだけです。

一度にたくさんのメソッドを覚えるのは大変なので、忘れてしまったらまたこの記事を読み返してみてください。

この記事を書いた人

Unityを使ったiOSアプリのリリース、フリマサイト運営の経験があります。

経験した言語はC、C#、Javascript、R、Python、Ruby、PHPなど

言語が好きで、英語や中国、ドイツ語を勉強しました。
将来的には海外で生活したいです。

現在はRuby on Rails5やCocos2dxの勉強を主にしています。

ライターとしては
できるだけ初心者にわかりやすい文章になるように心がけています。

趣味は語学、読書です。

目次