Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.collect with an index

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)

like image 218
zoran119 Avatar asked Feb 24 '12 13:02

zoran119


People also ask

Can you index a collection in Java?

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 collection?

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 −

How do you find the index of an element in a collection?

The index of a particular element in an ArrayList can be obtained by using the method java. util. ArrayList. indexOf().


6 Answers

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"]] 
}
like image 91
Beryllium Avatar answered Oct 03 '22 22:10

Beryllium


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.

like image 23
Rob Hruska Avatar answered Oct 03 '22 20:10

Rob Hruska


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)
}
like image 21
Matt Avatar answered Oct 03 '22 22:10

Matt


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]]
like image 26
dstarh Avatar answered Oct 03 '22 20:10

dstarh


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 image 43
pickypg Avatar answered Oct 03 '22 22:10

pickypg


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

like image 29
dexterous Avatar answered Oct 03 '22 21:10

dexterous