2012-04-30 9 views
6

¿Hay alguna manera de eliminar la variable "i" en el siguiente ejemplo y seguir teniendo acceso al índice del artículo que se está imprimiendo?groovy - ¿hay alguna variable implícita para obtener acceso al índice del artículo en "cada" método

def i = 0; 
"one two three".split().each { 
    println ("item [ ${i++} ] = ${it}"); 
} 

=============== EDITAR ================

he encontrado que una posible solución es para utilizar el método "eachWithIndex":

"one two three".split().eachWithIndex {it, i 
    println ("item [ ${i} ] = ${it}"); 
} 

Háganme saber si hay otras soluciones.

Respuesta

11

puede utilizar eachWithIndex()

"one two three four".split().eachWithIndex() { entry, index -> 
     println "${index} : ${entry}" } 

esto se traducirá en

0 : one 
1 : two 
2 : three 
3 : four 
0

No estoy seguro que otras soluciones '' que están buscando ... La única otra cosa que puede hacer lo que pueda pensar (con Groovy 1.8.6), es algo así como:

"one two three".split().with { words -> 
    [words,0..<words.size()].transpose().collect { word, index -> 
    word * index 
    } 
} 

como se puede ver, esto permite s usted para usar collect con un índice también (ya que no existe el método collectWithIndex).

+0

wow, esto es descabellada, murdochjohn lo hizo bien – loteq

+0

@loteq Eso es básicamente lo que he dicho ... Después de hacer las cosas bien, el PO _ pide "otras soluciones" _ por alguna razón. Además, si desea usar un índice en 'collect',' find', es la única forma que no sea una var ... –

+0

Respuesta interesante, pero el uso de 'with' dificulta la legibilidad de esta solución IMO. Conecté tu respuesta en la mía, que generaliza esto en un método 'enumerate' = D – epidemian

0

Otro enfoque, si desea utilizar el índice de la colección de otros métodos de each es definir un método enumerate que devuelve pares [index, element], análogo a Python's enumerate:

Iterable.metaClass.enumerate = { start = 0 -> 
    def index = start 
    delegate.collect { [index++, it] } 
} 

Así, por ejemplo:

assert 'un dos tres'.tokenize().enumerate() == [[0,'un'], [1,'dos'], [2,'tres']] 

(aviso de que estoy usando tokenize en lugar de split porque el primero devuelve un iterable, mientras que los rendimientos posteriores a String[])

Y podemos usar esta nueva colección con each, como lo hubiera querido:

'one two three'.tokenize().enumerate().each { index, word -> 
    println "$index: $word" 
} 

O podemos utilizarlo con otros métodos de iteración: D

def repetitions = 'one two three'.tokenize().enumerate(1).collect { n, word -> 
    ([word] * n).join(' ') 
} 
assert repetitions == ['one', 'two two', 'three three three'] 

Nota: Otra forma de definir el método enumerate, seguido de tim_yates 'more functional approach es:

Iterable.metaClass.enumerate = { start = 0 -> 
    def end = start + delegate.size() - 1 
    [start..end, delegate].transpose() 
} 
Cuestiones relacionadas