Ruby

Rubyのmapやselectでもeach_with_indexみたいにindexを使いたいときはEnumerator#with_index


Rubyで便利なEnumerable module.

eachが定義されているクラスであればincludeできるこのmoduleですが、Array Hashなどが最初からincludeしており、そのおかげでeach_with_index, min, max, select, map, all?/any?, sort ... などといったrubyでは欠かせないメソッド群が使用できるようになります。


Enumerableなクラスのインスタンス(Enumerator)はEnumerator#with_indexが使える

さて、このように様々なメソッドがあるEnumerableですが、時たま使いたくなるのはeach_with_indexのwith_indexの部分。

要素ごとにリストの中での位置を何らかの方法で取得するのもいいんですが、mapやselectのときでも最初からindex使えるといいのになーと思って調べていたらEnumerator#with_indexなる便利なものがあるやんけ。

[100, 200, 300].map.with_index { |num, index| [num, index] }

#=> [[100, 0], [200, 1], [300, 2]]

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
.select.with_index { |num, index|( num % (index + 1)).zero? }
#=> [1, 5, 144]

ここでのミソは、Enumerableのメソッドの内幾つかのメソッドがブロックをとらないときにEnumeratorを返すところであり、以下のメソッド群がそれに当たります。


  • map / colect

  • flat_map / collect_concat

  • cycle

  • find / detect

  • drop_while

  • each_cons

  • each_entry

  • each_slice

  • each_with_index

  • each_with_object

  • find_all / select

  • find_index

  • group_by

  • max_by / min_by / minmax_by

  • partition

  • reject

  • reverse_each

  • slice_before

  • sort_by

  • take_while

これは便利!


参照: Ruby リファレンスマニュアル

http://docs.ruby-lang.org/ja/2.3.0/class/Enumerable.html#I_COLLECT

もう一回丁寧に読む事にする。