Is there a .collect with an index? I want to do something like this:

def myList = [
    [position: 0, name: 'Bob'],
    [position: 0, name: 'John'],
    [position: 0, name: 'Alex'],
]

myList.collect { index ->
    it.position = index
}

(ie. I want to set position to a value which will indicate the order in the list)


Solution 1:

Since Groovy 2.4.0 there is a withIndex() method which gets added to java.lang.Iterable.

So, in a functional fashion (no side effect, immutable), it looks like

def myList = [
  [position: 0, name: 'Bob'],
  [position: 0, name: 'John'],
  [position: 0, name: 'Alex'],
]

def result = myList.withIndex().collect { element, index ->
  [position: index, name: element["name"]] 
}

Solution 2:

eachWithIndex would probably work better:

myList.eachWithIndex { it, index ->
    it.position = index
}

Using a collectX doesn't really seem necessary since you're just modifying the collection and not returning particular pieces of it into a new collection.

Solution 3:

Slightly groovier version of collectWithIndex:

List.metaClass.collectWithIndex = {body->
    def i=0
    delegate.collect { body(it, i++) }
}

or even

List.metaClass.collectWithIndex = {body->
    [delegate, 0..<delegate.size()].transpose().collect(body)
}