麻布十番で働くデータ分析者のブログ

グロースハック、プログラミング、データ分析の色々を発信します

繰り返しや配列処理(mapやinjectメソッド)

プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで (Software Design plusシリーズ)

さて、3日目やっていきましょう。今日は繰り返しや配列処理について学んでました。 ちなみにこの章は長いので2日に分かれています。

前回のエントリは下記リンクよりどうぞ

nimi0370376.hatenablog.com

今回は、配列とかブロックとかをやっていきます。 mapメソッドなどよく見るけど実際どんな動きをするのかよくわかってなかったものについて深掘りしていきます。

Rubyの配列に関して

まず、Rubyの配列に関してですが

a = [1,2,3]

a #=> [1,2,3]

みたいなやつですね。 基本的になんでも入れることできます。

要素を取り出す際には、

# 配列名[添字]
a[0]

でいけます。

さらに添字をして値を代入すると、指定した要素を変更することができる。

配列[添字] = 新しい値

もし大きな添字をした場合は、間がnilになる。

a = [1,2,3]
a[4] = 50

a #=> [1,2,3,nil,50]

<<を使うと配列の最後に要素を追加できる。

do...endと{ }

do … endを使う代わりに{}を使うことでブロックを表現することができる。

numbers = [1,2,3,4}
sum = 0

numbers.each do |n1|
sum += n1
end

numbers = [1,2,3,4}
sum = 0

numbers.each {|n2| sum += n2}

は同じ意味。

do … end と {}の使い分けは明確に決まっていない。 ただし、1行で簡潔に書きたいときは{}を使うと見やすい。

配列の様々なメソッド

ここからは配列や繰り返し処理に関する様々なメソッドを復習していきます。

map(collect)メソッド

配列でeachメソッドの次に使用頻度が高いメソッドといえばmapメソッドです。 mapメソッドは各要素に対してブロックを評価した結果を新しい配列にして返します。

numbers = [1,2,3,4}
# ブロックの戻り値が新しい配列の各要素になる
new_numbers = numbers.map{ |n| n*10}

空の配列を用意して、他の配列をループ処理した結果を空の配列に詰め込んでいくような処理の大半は、mapメソッドに置き換えることができる。

select / find_all / rejectメソッド

selectメソッドは、各要素に対してブロックを評価し、その戻り値が真の要素を集めた配列を返すメソッドです。 次の配列では、偶数だけを集めた配列を作ることができます。

numbers = [1,2,3,4,5,6]
# ブロックの戻り値が真になったものだけを集めることができる
even_numbers = numbers.select {|n| n.even?}
even_numbers

rejectメソッドはその逆で、ブロックの戻り値が偽になったものを返します。

inject(reduce)メソッド

今日学んだメソッドの中では最も複雑な動きをするメソッドです。

numbers = [1,2,3,4]
sum = 0
numbers.each {|n| sum += n}
sum
numbers = [1,2,3,4]
sum = numbers.inject(0) { |result,n| result + n}
sum

以上のコードは次のようになっている。 ((((0+1)+2)+3)+4)

簡単に書いておくと、numbersから2つずつ入れることができる。 一気にsumを計算できる。

&とシンボルでシンプルに記述

以下の条件の時、&とシンボルで簡単に配列を書くことできる。

  • ブロック引数が1個だけ
  • ブロックの中で呼び出すメソッドには引数がない
  • ブロックの中では、ブロック引数に対してメソッドを1回呼び出す以外の処理がない
[1,2,3,4,5,6].map {|n| n.odd?}
# こう書き換えることができる
[1,2,3,4,5,6].map(&:odd?)

Rubyでの範囲

eachメソッドに似ているが、一気にまとめて判定したいときは範囲が便利 Rubyでの範囲は下記のようにかける。

最初の値..最後の値(最後の値を含む)
最初の値…最後の値(最後の値を含まない)

配列に対して添字の代わりに範囲オブジェクトを渡すと、指定した範囲の要素を取得することができる。

a = [1,2,3,4,5]
a[1..3] #=> [2,3,4]

値が連続する処理は、splat展開でかける

(1..5).to_a #=> [1,2,3,4,5]
[*1..5] #=> [1,2,3,4,5]

今回は、こんな感じです。明日続きを更新していきます。