LoginSignup
3
3

More than 5 years have passed since last update.

モンキーパッチ:Enumerable#select_index と Enumerable#reject_index

Last updated at Posted at 2014-06-09

Enumerable#selectEnumerable#find_all)ならば要素配列が返ってきますが、位置(index)だけ返ってくるメソッドが欲しかったので、モンキーパッチを書きました。

Enumerable#findに対するEnumerable#selectと同じ関係で、Enumerable#find_indexに対するEnumerable#select_indexというメソッドです。
ついでにEnumerable#selectに対するEnumerable#rejectと同じ関係で、Enumerable#select_indexに対するEnumerable#reject_indexも作りました。

Ruby 1.9以上で使えます。多分1.8でも使えるんじゃないかとおもいます。

  • Enumerable#select_index:各要素に対してブロックを評価した値が真であった位置を全て含む配列を返します。エイリアスとしてEnumerable#find_all_indexを設定しています。
  • Enumerable#reject_index:各要素に対してブロックを評価した値が真であった位置を全て含む配列を返します。

モンキーパッチ

module Enumerable 
  def select_index
    return to_enum(__method__) unless block_given?
    values = []
    self.each_with_index{ |item, i| values << i if yield(item) }
    values
  end
  alias :find_all_index :select_index

  def reject_index
    return to_enum(__method__) unless block_given?
    values = []
    self.each_with_index{ |item, i| values << i unless yield(item) }
    values
  end
end

使用例

a = (0..19).map{ rand(100) }
# => [29, 73, 39, 71, 4, 71, 43, 65, 61, 21, 53, 62, 47, 72, 78, 96, 1, 2, 44, 70]
a.select_index { |item| item > 70 }
# => [1, 3, 5, 13, 14, 15]
a.reject_index { |item| item > 70 }
# => [0, 2, 4, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19]
s_idx = a.select_index
# => #<Enumerator: ...>
s_idx.each { |item| item > 70 }
# => [1, 3, 5, 13, 14, 15]
r_idx = a.reject_index
# => #<Enumerator: ...>
r_idx.each { |item| item > 70 }
# => [0, 2, 4, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19]

参考サイト

# おまじない
return to_enum(:leapfrog) unless block_given?

ブロックが指定されなかったときは、自身のメソッド名を引数にしてenum_forでEnumeratorを返してやればよいわけですね。
※Kernel.#methodは現在のメソッド名を返します。

3
3
0

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
  3. You can use dark theme
What you can do with signing up
3
3