Enumerable#mapの途中でindexにアクセスしたい
次のようなEnumerableをincludeしたクラスがあって、
class Foo include Enumerable def each ["a","b","c"].each{|i| yield i } # もちろんこんな実装じゃないよ end end
これのEnumerable#mapのブロック中で、現在の要素のインデックスが必要になったので、↓こうしてみた。
class Foo include Enumerable def each $index = 0 ["a","b","c"].each{|i| yield i $index += 1 } end end
これで「$index」で現在の要素のインデックスにアクセスできるようになる。mapだけでなくinjectとかでももちろん使える。
f = Foo.new puts "---map" puts f.map{|i| "#{$index}:#{i}" }.join("\n") puts "---each" f.each{|i| puts "#{$index}:#{i}" } puts "---inject" puts f.inject(""){|r,i| r << "#{$index}:#{i}\n" }
実行結果です。
---map 0:a 1:b 2:c ---each 0:a 1:b 2:c ---inject 0:a 1:b 2:c
ただし、グローバル変数なので、複数スレッドで使う場合に不整合になりやすい。注意。あと、イテレート中にイテレートとかしてもまずい。・・・やっぱ微妙だなー。↓こんなんの方がましかなー。
j=-1;puts f.map{|i| "#{j+=1}:#{i}" }.join("\n")