groovy injectがよくわからない - rubyのレファレンスを参照 2007/07/22

injectがよくわからないので考えてみる。

rubyのinjectと似ているらしいのでrubyの説明をさがしてみる。

inject([init]) {|result, item| ... } (ruby 1.7 feature)
最初に初期値 init と self の最初の要素を引数にブロックを実行します。2 回目以降のループでは、前のブロックの実行結果と self の次の要素を引数に順次ブロックを実行します。そうして最後の要素まで繰り返し、最後のブロックの実行結果を返します。

要素が空の場合は init を返します。

初期値 init を省略した場合は、最初に先頭の要素と 2 番目の要素をブロックに渡します。この場合、要素が 1 つしかなければブロックを実行せずに最初の要素を返します。要素が空なら nil を返します。Rubyリファレンスマニュアル - Enumerable


Enumerableは、辞書で調べると、【形】 可算{かさん}の とか 帰納的{きのうてき}という意味があります。

えーと
例えば、
[1,2,3,4,5]という配列があって、
[1, 2, 3, 4, 5].inject(0){i, j -> i + j }
と書く場合は、えーと、[1,2,3,4,5]という配列があって、それにinjectという命令をだして、その初期値が0で、
ループ開始は、i の値は、初期値の0,   j は配列の最初の値で、1になって、i + jが次のループの i になる。
イメージしやすくするために、下記のようなコードを実行すると、

println( "result:" + [1,2,3,4,5].inject(0){i, j -> print "(${i} + ${j}) "; i + j })

結果は、
(0 + 1) (1 + 2) (3 + 3) (6 + 4) (10 + 5) result:15

となる。

少しはイメージできるかな。

h-index - 情報食物連鎖末端でgroovy



というのがあった。

単純にコードのうつしかえをしてみようとしたが、Arrayを拡張したような使い方?(なんという仕組みだろう)をgroovyで表現する方法がわからなかったので、それは断念。


class h {
/* static */
static def hiindex (arr){
arr.reverse().inject( 0 ){ result, item -> if(item <= result) return result ; result + 1}
}

static void main(args) {

def h = {
it.reverse().inject( 0 ){ result, item -> if(item <= result) return result ; result + 1 }
}

println( "result:" + [1,2,3,4,5].inject(0){i, j -> print "(${i} + ${j}) "; i + j })
println( [1,2,3,4,5].reverse().inject( 0 ){ result, item -> if(item <= result) return result ; result + 1})
println( [0,10,20,30,40].reverse().inject( 0 ){ result, item -> if(item <= result) return result ; result + 1})
println(hiindex([0,10,20,30,40]))

assert 4 == h([0,10,20,30,40])
assert 4 == h([0,10,20,30,40])
assert 4 == h([10,20,30,40])
assert 3 == h([20,30,40])
assert 2 == h([30,40])
assert 1 == h([40])

assert 3 == h([1,2,3,4,5])
assert 2 == h([1,2,3,4])
assert 2 == h([1,2,3])
assert 1 == h([1,2])
assert 1 == h([1])

assert 3 == h([3,3,3])
assert 2 == h([3,3])
assert 1 == h([3])

assert 0 == h([0,0])
assert 0 == h([0])
assert 0 == h([])

}

}

: