search
LoginSignup
37

More than 3 years have passed since last update.

posted at

updated at

[Ruby]配列に対する繰り返し処理まとめ

よく使う配列のメソッド

each

ブロックに繰り返し要素を渡す。

each
# すべての要素の和を求める
numbers = [1, 2, 3, 4, 5]
sum = 0
numbers.each { |n| sum += n }

sum #=> 15

delete_if

指定した条件に一致する要素を削除する。

delete_if
# 奇数を削除する
numbers = [1, 2, 3, 4, 5]
numbers.delete_if { |n| n.odd? }

numbers #=> [2, 4]

map

ブロックが返す値からなる配列を作成する。

map
# すべて2倍にした配列を返す
numbers = [1, 2, 3, 4, 5]
double_numbers = numbers.map { |n| n * 2 }

double_numbers = [2, 4, 6, 8, 10]

Note:
mapcollectと同義

select

ブロックが真を返す要素からなる配列を作成する。

select
# 奇数を集める
numbers = [1, 2, 3, 4, 5]
odd_numbers = numbers.select { |n| n.odd? }

odd_numbers #=> [1, 3, 5]

Note:
selectfind_allと同義```

reject

ブロックが偽を返す要素からなる配列を作成する。

reject
# 2で割れる数を除く
numbers = [1, 2, 3, 4, 5]
odd_numbers = numbers.reject { |n| n % 2 == 0 }

odd_numbers #=> [1, 3, 5]

find

ブロックが真となる最初の要素を返す。

find
# 最初の偶数を探す
numbers = [1, 2, 3, 4, 5]
even_number = numbers.find { |n| n.even? }

even_number #=> 2

Note:
finddetectと同義
finddetectEnumerableモジュールのメソッド

inject

たたみ込み演算をおこなう。

indect
# すべての要素の和を求める
numbers = [1, 2, 3, 4, 5]
sum = numbers.inject(0) { |result, n| result + n }

sum #=> 15

ブロックの第一引き数は、

  • 1回目のみinjectの引き数
  • 2回目以降は前回のブロックの返り値

ブロックの第二引き数は、配列の各要素が順に入る。

上のコードの処理の流れ

  1. result = 0, n = 1 → 0 + 1 = 1
  2. result = 1, n = 2 → 1 + 2 = 3
  3. result = 3, n = 3 → 3 + 3 = 6
  4. result = 6, n = 4 → 7 + 4 = 10
  5. result = 10, n = 5 → 10 + 5 = 15

Note:
injectreduceと同義

簡潔に書く

メソッドにブロックを渡す代わりに、&:メソッド名を引き数として渡す。


numbers = [1, 2, 3, 4, 5]

# これを
odd_numbers = numbers.select { |n| n.odd? }

# こう
odd_numbers = numbers.select(&:odd?)

次の条件を満たす場合に使うことができる。

条件

  • ブロック引数が1つだけ
  • ブロック内で呼び出すメソッドに引数がない
  • ブロック内は、ブロック引数に対してメソッドを1回呼び出す処理のみ

(追記)正確には、、ブロック引き数が2つでも使える場合があります。
以下コメントからの引用

「メソッドにブロックを渡す代わりに、&:メソッド名を引き数として渡す。」についてですが,

a = [1, 2, 3]
a.inject(&:+) # => 6

という例もあります。
inject(&:+) はほぼinject{ |r, x| r.+(x) }です。
つまり,ブロックパラメーターが二つ以上の場合にもこういう記法が使えます。

添字付きの繰り返し

  • each_with_index
  • with_index

each_with_index

ブロックに繰り返し要素と添字を渡す。

each_with_index
# i には 0, 1, 2 がはいる
animals = ["dog", "cat", "mouse"]
animals.each_with_index { |animal, i| puts "#{i + 1}. #{animal}" }

#=>
# 1. dog
# 2. cat
# 3. mouse

with_index

each以外のメソッドに添え字を付ける場合は、各メソッドとwith_indexメソッドを組み合わせる。

map.with_index
# map に添え字を付ける
animals = ["dog", "cat", "mouse"]
animals.map.with_index { |animal, i| "#{i + 1}. #{animal}" }

#=> ["1. dog", "2. cat", "3. mouse"]

添字を0以外から始める

with_indexに引き数を渡す。

with_index(1)
# 添字を 1 から始める
animals = ["dog", "cat", "mouse"]
animals.map.with_index(1) { |animal, i| "#{i}. #{animal}" }

#=> ["1. dog", "2. cat", "3. mouse"]

配列の配列に対する繰り返し

ブロック引き数に配列が渡ってくるときは、ブロック引き数を複数個用意する。

dimensions = [
    # [縦, 横]
    [10, 20],
    [30, 40],
    [50, 60],
]

# それぞれの面積を求める
areas = []

# これを
dimentions.each { |dimention| areas << dimention[0] * dimention[1] }

# こう
dimentions.each { |length, width| areas << length * width }

areas #=> [200, 1200, 3000]

添字を付ける

with_index + ブロック引き数を()で囲む。

dimensions = [
    # [縦, 横]
    [10, 20],
    [30, 40],
    [50, 60],
]

dimensions.each.with_index do |(length, width), i|
    puts "#{length}, #{width}, #{i}"
end

#=>
# 10, 20, 0
# 30, 40, 1
# 50, 60, 2

参考文献

プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで|技術評論社

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
37