Tuesday, August 18, 2020 / Groovy

Groovy で collectWithIndex 的な機能を実現する

Groovy で java.util.Collection コレクション に対するメソッドとして eacheachWithIndex があるので、 同じように collect にも collectWithIndex があるのかと思ったらない。
そこでそれを実現する方法を考えてみた。

each, eachWithIndex

Groovy で リストなどを別のリストにつくりかえる場合。 たとえば each を使って実現できる。こんな風に。

def itemList = ['a','b','c']
def newItemList = []
itemList.each {
    newItemList << "- $it"
}
println newItemList.join(System.getProperty('line.separator'))

実行結果:

- a
- b
- c

番号付きリストにしたければ:

def itemList = ['a','b','c']
def newItemList = []
itemList.eachWithIndex { it,index->
    newItemList << "${index+1}. $it"
}
println newItemList.join(System.getProperty('line.separator'))

実行結果:

1. a
2. b
3. c

collect

each の代わりに collect を使えば スッキリ実装できる:

def itemList = ['a','b','c']
def newItemList = itemList.collect { newItemList << "- $it" }
println newItemList.join(System.getProperty('line.separator'))

番号付きリストをこの方法でつくるには collectWithIndex を使えばいいと思ったが、そんなメソッドはなかった。

ならば transpose を使おう:

def itemList = ['a','b','c']
def indexList = (0..<itemList.size).collect { it } // [0,1,2] のリストを生成
def newItemList = [itemList, indexList].transpose().collect { item, index-> "${index+1}. $item" }
println newItemList.join(System.getProperty('line.separator'))

実行結果:

1. a
2. b
3. c

できた。

withIndex を使え

StackOverflowwithIndex を使うもっとよい方法が書いてあった.

def itemList = ['a','b','c']
def newItemList = itemList.withIndex().collect { item, index-> "${index+1}. $item" }
println newItemList.join(System.getProperty('line.separator'))