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)
An index can be defined on a Collection property (java. util. Collection implementation) or Array. Setting such an index means that each of the Collection's or Array's items is indexed.
What is index-based I/O ArrayList collection in C#? CsharpProgrammingServer Side Programming. ArrayList class represents an ordered collection of an object that can be indexed individually. It is an alternative to an array. The following table lists some of the commonly used properties of the ArrayList class −
The index of a particular element in an ArrayList can be obtained by using the method java. util. ArrayList. indexOf().
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"]]
}
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.
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)
}
This should do exactly what you want
List.metaClass.collectWithIndex = {cls ->
def i = 0;
def arr = [];
delegate.each{ obj ->
arr << cls(obj,i++)
}
return arr
}
def myCol = [
[position: 0, name: 'Bob'],
[position: 0, name: 'John'],
[position: 0, name: 'Alex'],
]
def myCol2 = myCol.collectWithIndex{x,t ->
x.position = t
return x
}
println myCol2
=> [[position:0, name:Bob], [position:1, name:John], [position:2, name:Alex]]
Without adding any extension methods, you can do this in a pretty straightforward way:
def myList = [1, 2, 3]
def index = 0
def myOtherList = myList.collect {
index++
}
It would certainly be useful for this method to exist automatically though.
Like dstarh said, unless you're looking for a non-destructive method that returns a new map with your indices populated, Rob Hruska's answer is what you're looking for.
dstarh's answer provides you the non-destructive version of collectWithIndex
, but handles the actual collection of results too.
I usually find it best to delegate such heavy lifting to the receiving object so as to play nice with polymorphic collect
implementations, i.e., in case a specific class implements collect
differently (than just putting the results in an array), having collectWithIndex
delegate to it will ensure uniform behaviour. Here's how the code would look:
@Category(List)
class Enumerator {
def collectWithIndex(Closure closure) {
def index = 0
this.collect { closure.call(it, index++) }
}
}
use(Enumerator) {
['foo', 'bar', 'boo', 'baz'].collectWithIndex { e, i ->
[index: i, element: e]
}
}
Refer to this gist for an example for both eachWithIndex
and collectWithIndex
.
Also, like the comments to your question state, there are two Jira issues open for the feature we've described- GROOVY-2838 & GROOVY-3797
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With