Enumerableモジュールを機能(ほぼ)全部まとめ 〜 select, inject, take などなど


# はじめに
eachやmap(collection)だけ使っているとなかなかコードが洗練されない
そこでEnumerableモジュールを継承しているクラスArray、Hash等で使えるメソッドを例示して、
同じ処理をeachで書いた場合の例をも書いて便利さを確認していきたい

あまりにコレは使いどころがないなぁと言うメソッドは省いている(#zipとか)
こういうところで使うよと言うのがあればコメントや編集依頼をいただけると助かる
また, #lazyはまた毛色が違うので省いている。lazyの実作業での使いどころがいまいちわからない


# all?

すべての要素がブロック内の条件式を満たしていればtrueを返す

## 使い方

```
[1,2,3].all? { |v| v > 0 }
=> true

[1,2,3].all? { |v| v > 1 }
=> false
```

### eachで書いた場合

```
flg = true
[1,2,3].each do |v|
  if v <= 0
    flg = false
    break
  end
end
p flg
=> true
```

# any?

すべての要素のうち一つでもブロック内の条件式を満たせばtrueを返す

## 使い方

```
[1,2,3].any? { |v| v == 2 }
=> true
```

### eachで書いた場合

```
flg = false
[1,2,3].each do |v|
  if v == 2
    flg = true
    break
  end
end
p flg
=> true
```

# collect, map

すべての要素をブロック内で評価した配列を返す
collectとmapは同じ動きをする
mapの方がよく使われる気がする

eachじゃなくてmapを使いこなせるとRubyを使ってる感が出てくるよね

## 使い方

```
# 各項を2倍にした配列を返す
[1,2,3].collect { |v| v * 2 }
=> [2, 4, 6]

[1,2,3].map { |v| v * 2 }
=> [2, 4, 6]
```

### eachで書いた場合

```
result = []
[1,2,3].each do |v|
  result << v * 2
end
p result
=> [2, 4, 6]
```

# collect_concat, flat_map

すべての要素をブロック内で評価した配列を展開して返す
collect_concatとflat_mapは同じ動きをする
map と flatten組み合わせた動きをする

下記の例のようにmap + flattenの方が可読性が高い気もする

## 使い方

```
# 各項を2倍にした配列を返す
[[1, 2], [3, 4]].flat_map { |v| v.map { |cv| cv * 2 } } 
=> [2, 4, 6, 8]

#map と flattenを組み合わせた場合
[[1, 2], [3, 4]].map { |v| v.map { |cv| cv * 2 } }.flatten
=> [2, 4, 6, 8]
```

### eachで書いた場合

```
result = []
[[1, 2], [3, 4]].each do |v|
  v.each do |cv|
    result << cv * 2  
  end
end
p result
=> [2, 4, 6, 8]
```

# count

すべての要素をブロック内で評価して真の物の数を返す
ブロックがない場合はsizeやlengthと同じ要素数を返す

## 使い方

```
[1,2,3].count
=> 3 #要素数

#値が3のもの数
[1,2,3].count(3)
=> 1 

# 文字列でも大丈夫
["1","2","3"].count("1")
=> 1 

# 奇数の数を返す
[1,2,3].count{ |v| v.odd? }
=> 2

# selectで絞り込んでから配列のサイズを数えるとこうも書ける
[1,2,3].select{ |v| v.odd? }.size

```

### eachで書いた場合

```
result = 0
[1,2,3].each do |v|
  result += 1 if v.odd?
end
p result
=> 2
```


# detect, find

すべての要素をブロック内で評価して真になった最初の要素を返し
それ以降の配列の要素を評価しない

ある条件の要素があるかどうかチェックするany?や
ある条件に合致する要素すべてを取りだすselectの方が使う場面が多い気もする

detectよりfindの方がよく使うかな

## 使い方

```
# 配列の中から3~5の値の最初の要素を返す
[1,3,7].detect { |v| (3..5).include?(v) } 
=> 3 

[1,3,7].find { |v| (3..5).include?(v) } 
=> 3 
```

### eachで書いた場合

```
result = nil
[1,3,7].each do |v|
  if (3..5).include?(v)
    result = v
    break
  end
end
p result
=> 3 
```

# drop

先頭から引数のInteger数の要素を捨てて、 残りの要素を配列で返す
引数が配列のサイズより大きい時でもエラーにならずに空の配列を返してくれるのが嬉しい

## 使い方

```
[1,2,3,4].drop(2)
=> [3.4]
 
# 配列のsizeより大きくてもエラーにならない
[1,2,3,4].drop(5)
=> []


```

### eachで書いた場合

```
result = []
drop_num = 2
i = 0
[1,2,3,4].each do |v|
  i += 1
  next if i <= drop_num
  result << v
end
p result
=> [3.4]

# each_with_indexで配列のindex番号をつけても書ける、当然dropを使えばもっと楽
result = []
drop_num = 2
[1,2,3,4].each_with_index do |v, i|
  next if i < drop_num
  result << v
end
p result
=> [3.4]

```

# take

先頭から引数のInteger数の要素を取り出してその配列で返す
引数が配列のサイズより大きい時でもエラーにならずに空の配列を返してくれるのが嬉しい

dropとtakeは対になっている機能なので合わせて覚えておくと良い

## 使い方

```
[1,2,3,4].take(2)
=> [1.2]
 
# 配列のsizeより大きくてもエラーにならない
[1,2,3,4].take(5)
=> [1, 2, 3, 4]


```

### eachで書いた場合

```
result = []
take_num = 2
i = 0
[1,2,3,4].each do |v|
  i += 1
  break if i > take_num
  result << v
end
p result
=> [1.2]

# each_with_indexで配列のindex番号をつけても書ける、当然takeを使えばもっと楽
result = []
take_num = 2
[1,2,3,4].each_with_index do |v, i|
  break if i >= take_num
  result << v
end
p result
=> [1.2]
```

# drop_while

ブロック内の条件にヒットしたらそれ以前の要素を捨てて、残りの要素を配列で返す
ソート済みの配列で、ある条件より小さいものを捨てると言う場合、rejectと違ってすべて評価しないのでよいかも

## 使い方

```
[1,2,3,4].drop_while { |v|  v < 3 }
=> [3, 4]

# こちらだと4も評価している 
[1,2,3,4].reject { |v|  v < 3 }
=> [3, 4]
```

### eachで書いた場合

```
# だんだんつらくなってきた
result = []
drop_num = 2
i = 0
ary =[1,2,3,4]
ary.each do |v|
  i += 1
  next if i <= drop_num
  result = ary[(i - 1)..-1]
  break
end
p result
=> [3, 4]
```

# take_while

ブロック内の条件にヒットしなくなったら(偽を返したら)以降の要素を捨てて、残りの要素を配列で返す
drop_whileとでソート済みの配列の場合だと、ある条件より小さいものを捨てると言う場合、selectと違ってすべて評価しないのでよいかも

## 使い方

```
[1,2,3,4].take_while { |v| v < 3 }
=> [1, 2]

# こちらだと4も評価している
[1,2,3,4].select { |v| v < 3 }
=> [1, 2]
```

### eachで書いた場合

```
result = []
take_num = 2
i = 0
[1,2,3,4].each do |v|
  i += 1
  break if i > take_num
  result << v
end
p result
=> [1, 2]
```

# each_with_index

要素とその何番目かを表す添字のインデックスをブロックに渡して処理をする
each_with_indexよりmap.with_indexを使って添字を使った配列を返すほうが使う気がする

## 使い方

```
ary = []
[1,9,5,2].each_with_index { |v, i|  ary << [v, i] }
p ary
=> [[1, 0], [9, 1], [5, 2], [2, 3]]


# map.with_indexを使うとこんな感じでかける
[1,9,5,2].map.with_index { |v, i| [v, i] }
=> [[1, 0], [9, 1], [5, 2], [2, 3]]
```

### eachで書いた場合

```
result = []
i = 0
[1,9,5,2].each do |v|
  result << [v, i]
  i += 1
end
p result
=> [[1, 0], [9, 1], [5, 2], [2, 3]]
```

# to_a, entries

すべての要素を含む配列を返す(って説明を見るけどいまいちピンとこない)
hashを [key, value] の組み合わせの配列を返すときに使ったりするかな。

Railsの場合はActiveRecordのオブジェクトをキャッシュで格納するときに使ったりするかな

```
User.where(state: "alive").to_a
```


## 使い方

```
{ a: 1, b: 2, c:3 }.entries
=> [[:a, 1], [:b, 2], [:c, 3]]


{ a: 1, b: 2, c:3 }.to_a
=> [[:a, 1], [:b, 2], [:c, 3]]
```

### eachで書いた場合

```
result = []
{ a: 1, b: 2, c:3 }.each do |v|
  result << [v.first.to_s, v.last]
end
p result
=> [[:a, 1], [:b, 2], [:c, 3]]
```


# find_all, select

各要素をブロック内で評価して真になったものだけの配列を返す。全部偽だった場合は空の配列を返す

select + mapをつなげて使うことがままあるかな

## 使い方

```
[1, 2, 3, 4].find_all { |v| v.even? }
=> [2, 4]


# こうとも書ける
[1, 2, 3, 4].select(&:even?)
=> [2, 4]
```

### eachで書いた場合

```
result = []
i = 0
[1, 2, 3, 4].each do |v|
  result << v if v.even?
end
p result
=> [2, 4]
```

# reject

各要素をブロック内で評価して偽になったものだけの配列を返す。全部真だった場合は空の配列を返す
selectの逆と考えれば良い、ブロック内でヒットした条件のものを削除したい場合に使う

## 使い方

```
[1, 2, 3, 4].reject { |v| v.even? }
=> [1, 3]


# こうとも書ける 書けるけどパフォーマンスは悪い
ary = [1,2,3,4]
ary - ary.select{ |v| v.even? }
=> [1, 3]
```

### eachで書いた場合

```
result = []
i = 0
[1, 2, 3, 4].each do |v|
  result << v if v.even?
end
p result
=> [2, 4]
```

# partition

各要素をブロック内で評価して真と偽になった2つの配列を返す
selectとrejectを実行したペアと考えればよい

## 使い方

```
[1, 2, 3, 4].partition { |v| v.even? }
=> [[2, 4], [1, 3]]
```

### eachで書いた場合

```
result = [[], []]
[1, 2, 3, 4].each do |v|
  if v.even?
    result[0] << v
  else
    result[1] << v
  end
end
p result
=> [[2, 4], [1, 3]]
```


# find_index, index(Arrayの場合)

各要素をブロック内で評価して最初に真になったものの添字(何番目か)を返す。全部偽だった場合はnil
Arrayの場合はindexメソッドが別名である。主にindexがある


## 使い方

```
[1, 2, 3, 4].find_index { |v| v.even? }
=> 1

# こうとも書ける
[1, 2, 3, 4].index { |v| v.even? }
=> 1

# Hashの場合に使う意味がたぶんないけどこう書ける
{a: 1, b: 2}.find_index { |v| v.last.even? }
=> 1
```

### eachで書いた場合

```
result = nil
index = 0
[1, 2, 3, 4].each do |v|
  if v.even?
    result = index
    break
  end
  index += 1
end
p result
=> 1
```

# first, last(Arrayの場合)

要素の最初の要素または、先頭から引数の数字個要素を取得する
Arrayの場合は後ろから取得する lastもある

空の配列の
引数なしの場合はnil、引数ありの場合はからの配列を返す動きをする
引数ありの場合はtakeメソッドを使ったほうがわかりやすい気もする


## 使い方

```
[1, 2, 3, 4].first
=> 1

# 引数があると
[1, 2, 3, 4].first(2)
=> [1, 2]

# lastの場合
[1, 2, 3, 4].last(2)
=> [3, 4]
```

### eachで書いた場合

```
#　引数なしのfirstはeachは使わない
result = [1, 2, 3, 4][0]
p result
=> 1

# [1, 2, 3, 4].first(2)をeachを使って書くと
result = []
index = 0
num = 2
[1, 2, 3, 4].each do |v|
  unless index < num
    break
  end
  result << v
  index += 1
  
end
p result
```

# grep

引数のpatternにマッチするすべての要素の配列を返す。
patternには===メソッドがあるものが必要。
具体的にはRegexpオブジェクトをつかって正規表現にマッチするものを抽出するのに使う

ブロックをつけると、マッチした配列の要素それぞれにブロックの要素を評価した結果を格納した配列を返す
Arrayの中身が単純なIntegerやStringじゃないと機能しないかな、他のクラスで上手く使いたかったらたぶん#===メソッドを拡張しておく必要がありそう。小難しいことするならselectメソッドを使ったほうが楽だろう

map + matchをまとめて使うイメージ

## 使い方

```
# ブロックなしの場合
["1", "2", "3"].grep(/2/)
=> ["2"]

# grepを使わないで書くとこんな感じ
["1", "2", "3"].map{ |v| v if v.match(/2/) }.compact
=> ["2"]

# ブロックありの場合 マッチした"2"を数字にしてから2倍する
["1", "2", "3"].grep(/2/){ |v| v.to_i * 2 }
=> [4]

```

### eachで書いた場合

```
# マッチした"2"を数字にしてから2倍する
result = []
["1", "2", "3", "4"].each do |v|
  if v.match(/2/)
    result << v.to_i * 2
  end
end
p result
=> [4]
```

# member?, include?

各要素が、引数と==の評価値を返す。要するに含まれていればtrue、含まれていなければfalseを返す

RailsのActiveSupportの機能にinclude?の逆のようなin?メソッドがある

## 使い方

```
[1, 2, 3].include?(2)
=> true
[1, 2, 3].member?(2)
=> true

# Railsのin?メソッドはinclude?の逆のイメージ
2.in?([1, 2, 3])
=> true
```

### eachで書いた場合

```
result = false
num = 2
[1, 2, 3].each do |v|
  if v == num
    result = true
    break
  end
end
p result
=> true
```

# inject, reduce

各ブロックの結果を順次格納した値を返す、引数は初期値となる引数を省略すると1つ目の実行結果が初期値となる
引数にSymbolオブジェクトを渡すと、各要素のSymbolで表されたメソッドを実行する :+を渡すと各要素の+メソッドを実行したっけかを返す

このメソッドは個人的に好き、一発でかけると気持ちいい

## 使い方

```
# 初期値100で各要素の和
[1, 2, 3].inject(100) { |sum, v| sum + v}
=> 106

# こうも書ける
[1, 2, 3].reduce(100) { |sum, v| sum + v}
=> 106

# 引数を省略した場合
[1, 2, 3].inject{ |sum, v| sum + v}
=> 6

# Symbolで渡してやるこうも書ける
[1, 2, 3].inject(:+)
=> 6

# サンプルのデータを作りたいときべんり
# 1〜3の値の配列をランダムにしたものとか
(1..3).inject([]){ |sum, v| sum << v}.shuffle
=> [1, 2, 3]
```

### eachで書いた場合

```
sum = 0
[1, 2, 3].each do |v|
  sum += v
end
p sum
=> 6
```


# max, max_by

各要素の最大値を返す、ブロックを渡さない場合は　<=>　メソッドで比較した結果を返す。
ブロックを渡す場合は、max_byの方がO(n)で実行できるらしい(この辺の説明は[ここ](http://docs.ruby-lang.org/ja/2.0.0/method/Enumerable/i/sort_by.html)を読むと良い)


## 使い方

```
[1, 2, 3].max
=> 3

# 比較条件がややこしい場合はこちら
["A", "bb", "ccc"].max_by { |a | a.length }
=> "ccc"
```

### eachで書いた場合

```
ary = [1, 2, 3]
max = ary.first

ary.each do |v|
  max = v if max < v
end
p max
=> 3
```


# min, min_by

各要素の最小値を返す、ブロックを渡さない場合は　<=>　メソッドで比較した結果を返す。
ブロックを渡す場合は、min_byもmax_byと同様にO(n)で実行できるらしい(この辺の説明は[ここ](http://docs.ruby-lang.org/ja/2.0.0/method/Enumerable/i/sort_by.html)を読むと良い)

## 使い方

```
[1, 2, 3].min
=> 1

# 比較条件がややこしい場合はこちら
["A", "bb", "ccc"].min_by { |a | a.length }
=> "A"
```

### eachで書いた場合

```
ary = [1, 2, 3]
min = ary.first

ary.each do |v|
  min = v if min > v
end
p min
=> 1
```

# sort, sort_by

各要素の並び替えた値を返す、ブロックを渡さない場合は　<=>　メソッドで比較した結果を返す。
ブロックを渡す場合は、sort_byもmax_byと同様にO(n)で実行できるらしい(この辺の説明は[ここ](http://docs.ruby-lang.org/ja/2.0.0/method/Enumerable/i/sort_by.html)を読むと良い)

## 使い方

```
[3, 2, 1].sort
=> [1, 2, 3]

# 比較条件がややこしい場合はこちら
["aaa", "b", "cccc"].sort_by { |a | a.length }
=> ["b", "aaa", "cccc"]
```

### whileで書いた場合

```
ary = [3, 2, 1]
i = 0

while i < ary.length
  j = 1
  while j < ary.length - i
    if ary[i] > ary[i+j]
      ary[i], ary[i+j] = ary[i+j], ary[i]
    end
    j += 1
  end
  i += 1
end
p ary
=> [1, 2, 3]
```


# reverse_each

逆順に各要素に対してブロックを評価する
使いどころはArray#rindexを他のEnumerableモジュールを適用しているものに実装する場合とかかな

## 使い方

```
[1, 2, 3].reverse_each { |v| p v}
3
2
1
=> [1, 2, 3]

```

### eachで書いた場合

```
[1, 2, 3].reverse.each do |v|
 p v
end
3
2
1
=> [3, 2, 1]
```

# 使いどころがよくわからん
zipとか、group_byとか

refs: 
  http://ruby-doc.org/core-2.3.0/Enumerable.html
  https://repl.it/languages/ruby