2012-02-24 9 views
28

¿Hay un .collect con un índice? Quiero hacer algo como esto:.collect con un índice

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

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

(es decir, quiero fijar position a un valor que indicará el orden en la lista.)

+2

parece que es una característica solicitada http: //jira.codehaus.org/browse/GROOVY-2838 – dstarh

+0

respondido con una solución real debajo de – dstarh

+0

Lo que no me gusta para coleccionar con el índice :) – dstarh

Respuesta

11

eachWithIndex probablemente funcionaría mejor:

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

El uso de un collectX realmente no parece necesario ya que solo está modificando la colección y no devolviendo piezas particulares de ella en una nueva colección.

+9

a menos que lo necesite para devolver una nueva colección – dstarh

+1

@dstarh - Correcto, pero la pregunta dice "Quiero establecer la posición en un valor", lo que haría que la colección parezca innecesaria. –

+4

de acuerdo, probablemente no sea necesario cobrar en este caso. Si estuviera en una cadena de otras llamadas, sería diferente. Todavía me gustaría ver un recopilatorio con el índice – dstarh

6

Esto debería hacer exactamente lo que quiere

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]] 
1

Como dstarh Dicho esto, a menos que usted está buscando un método no destructivo que devuelve un nuevo mapa con sus índices de población, la respuesta Rob Hruska 's es lo que 'que estas buscando.

La respuesta de dstarh le proporciona la versión no destructiva de collectWithIndex, pero maneja la colección real de resultados también.

por lo general me parece que lo mejor es delegar tal trabajo pesado con el objeto receptor con el fin de jugar bien con polimórficas collect implementaciones, es decir, en caso de que una clase específica implementa collect diferente (que poner los resultados en una matriz), que tiene collectWithIndex delegado asegurará un comportamiento uniforme. Así es como se vería el código:

@Category(List) 
class Enumerator { 
    def enumerateCollecting(Closure closure) { 
     def index = 0 
     this.collect { closure.call(it, index++) } 
    } 
} 

use(Enumerator) { 
    ['foo', 'bar', 'boo', 'baz'].collectWithIndex { e, i -> 
     [index: i, element: e] 
    } 
} 

Consulte this gist para un ejemplo tanto para eachWithIndex y collectWithIndex.

También, al igual que los comentarios a su estado cuestión, hay dos cuestiones Jira abierto para la función que hemos descrito- GROOVY-2383 & GROOVY-3797

13

poco más groovy versión de collectWithIndex:

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

o incluso

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

Sin agregar ningún método de extensión, puede hacerlo en una bonita recta orward way:

def myList = [1, 2, 3] 
def index = 0 
def myOtherList = myList.collect { 
    index++ 
} 

Sin duda, sería útil que este método exista automáticamente.

60

Dado que Groovy 2.4.0 hay un método withIndex() que se agrega al java.lang.Iterable.

Por lo tanto, de una manera funcional (ningún efecto secundario, inmutable), parece que

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"]] 
} 
+4

. Vote que esta debería ser la mejor respuesta. – solvingJ

Cuestiones relacionadas