Pregunta

Me gustaría un poco sorthand para esto:

Map rowToMap(row) {
    def rowMap = [:];
    row.columns.each{ rowMap[it.name] = it.val }
    return rowMap;
}

dada la forma en que el GDK cosas, me gustaría esperar a ser capaz de hacer algo como:

Map rowToMap(row) {
    row.columns.collectMap{ [it.name,it.val] }
}

pero no he visto nada en la documentación...me estoy perdiendo algo?o soy demasiado perezoso?

¿Fue útil?

Solución

Recientemente he encontré con la necesidad de hacer exactamente eso:convertir una lista en un mapa.Esta pregunta fue publicado antes de la Genial versión 1.7.9 salió, por lo que el método collectEntries todavía no existía.Funciona exactamente como el collectMap método lo que se propuso:

Map rowToMap(row) {
    row.columns.collectEntries{[it.name, it.val]}
}

Si por alguna razón usted está atascado con un mayor Groovy versión, la inject el método también puede utilizarse (como se propone aquí).Esta es una versión ligeramente modificada que toma solamente una expresión dentro de cierre (sólo para el bien de carácter ahorro!):

Map rowToMap(row) {
    row.columns.inject([:]) {map, col -> map << [(col.name): col.val]}
}

El + el operador también puede ser utilizado en lugar de la <<.

Otros consejos

Echa un vistazo a "inyectar".Real de programación funcional wonks llaman "doble".

columns.inject([:]) { memo, entry ->
    memo[entry.name] = entry.val
    return memo
}

Y, mientras estás en ello, es probable que desee definir métodos como Categorías en lugar de a la derecha en la metaClass.De esa manera, usted puede definir de una vez por todas las Colecciones:

class PropertyMapCategory {
    static Map mapProperty(Collection c, String keyParam, String valParam) {
        return c.inject([:]) { memo, entry ->
            memo[entry[keyParam]] = entry[valParam]
            return memo
        }
    }
}

Ejemplo de uso:

use(PropertyMapCategory) {
    println columns.mapProperty('name', 'val')
}

Fue el groupBy el método no está disponible cuando esta pregunta se la hicieron?

También, si vas a usar google colecciones (http://code.google.com/p/google-collections/), usted puede hacer algo como esto:

  map = Maps.uniqueIndex(list, Functions.identity());

ok...Yo he jugado con esto un poco más, y creo que esta es una genial método de...

def collectMap = {Closure callback->
    def map = [:]
    delegate.each {
        def r = callback.call(it)
        map[r[0]] = r[1]
    }
    return map
}
ExpandoMetaClass.enableGlobally()
Collection.metaClass.collectMap = collectMap
Map.metaClass.collectMap = collectMap

ahora cualquier subclase de Mapa o la Recolección de este método...

aquí yo lo uso para revertir la clave/valor en un Mapa

[1:2, 3:4].collectMap{[it.value, it.key]} == [2:1, 4:3]

y aquí yo lo uso para crear un mapa a partir de una lista

[1,2].collectMap{[it,it]} == [1:1, 2:2]

ahora acabo de pop esta en una clase que se llama como mi aplicación está empezando y que este método esté disponible a lo largo de mi código.

EDITAR:

para agregar el método para todas las matrices...

Object[].metaClass.collectMap = collectMap

Si lo que necesita es un simple par clave-valor, entonces el método de collectEntries debería ser suficiente.Por ejemplo

def names = ['Foo', 'Bar']
def firstAlphabetVsName = names.collectEntries {[it.charAt(0), it]} // [F:Foo, B:Bar]

Pero si quieres una estructura similar a la de un Multimap, en el que hay varios valores por clave, entonces usted quiere utilizar el groupBy método

def names = ['Foo', 'Bar', 'Fooey']
def firstAlphabetVsNames = names.groupBy { it.charAt(0) } // [F:[Foo, Fooey], B:[Bar]]

No puedo encontrar nada construida en...pero el uso de la ExpandoMetaClass puedo hacer esto:

ArrayList.metaClass.collectMap = {Closure callback->
    def map = [:]
    delegate.each {
        def r = callback.call(it)
        map[r[0]] = r[1]
    }
    return map
}

esto agrega el collectMap método a todas las ArrayLists...No estoy seguro de por qué añadir a la Lista o Colección no funcionaba..Supongo que es para otra pregunta...pero ahora puedo hacer esto...

assert ["foo":"oof", "42":"24", "bar":"rab"] ==
            ["foo", "42", "bar"].collectMap { return [it, it.reverse()] }

de la Lista a la calculada Mapa con un cierre...exactamente lo que estaba buscando.

Editar:la razón por la que no podía agregar el método de la Lista de interfaces y de la Colección fue porque yo no hice esto:

List.metaClass.enableGlobally()

después de que la llamada al método, usted puede agregar métodos a las interfaces..que en este caso significa mi collectMap método de trabajo en intervalos de tiempo como este:

(0..2).collectMap{[it, it*2]}

que da el mapa:[0:0, 1:2, 2:4]

¿Qué acerca de algo como esto?

// setup
class Pair { 
    String k; 
    String v; 
    public Pair(def k, def v) { this.k = k ; this.v = v; }
}
def list = [ new Pair('a', 'b'), new Pair('c', 'd') ]

// the idea
def map = [:]
list.each{ it -> map.putAt(it.k, it.v) }

// verify
println map['c']
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top