Question

J'aimerais avoir quelques sorthand pour cela:

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

compte tenu de la façon dont le FEU est, je m'attends à être en mesure de faire quelque chose comme:

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

mais je n'ai rien vu dans les docs...ai-je raté quelque chose?ou suis-je tout simplement trop paresseux?

Était-ce utile?

La solution

J'ai récemment tombé sur la nécessité de faire exactement cela:la conversion d'une liste sur une carte.Cette question a été posté avant Groovy version 1.7.9 est sorti, de sorte que la méthode collectEntries n'existaient pas encore.Il fonctionne exactement comme le collectMap méthode qui a été proposé:

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

Si pour quelque raison vous êtes coincé avec une ancienne version Groovy, le inject la méthode peut également être utilisée (comme l'a proposé ici).C'est une version légèrement modifiée qui ne prend qu'une expression à l'intérieur de la fermeture (juste pour le plaisir de caractère salvateur!):

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

L' + l'opérateur peut également être utilisé à la place de la <<.

Autres conseils

Découvrez "injecter".Réel de la programmation fonctionnelle wonks l'appeler "pli".

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

Et, pendant que vous y êtes, vous voulez probablement à définir des méthodes comme des Catégories au lieu de droite sur la métaclasse.De cette façon, vous pouvez le définir une fois pour toutes les Collections:

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

Exemple d'utilisation:

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

A l' groupBy méthode qui n'est pas disponible lorsque cette question a été posée?

Aussi, si vous êtes d'utiliser google collections (http://code.google.com/p/google-collections/), vous pouvez faire quelque chose comme ceci:

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

ok...J'ai joué avec ce un peu plus et je pense que c'est une super méthode...

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

maintenant, toute sous-classe de la Carte ou de la Collection de cette méthode...

ici, je l'utilise pour inverser la clé/valeur dans une Carte

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

et ici, je l'utilise pour créer une carte à partir d'une liste

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

maintenant, j'ai juste pop ce dans une classe qui est appelée que mon application est de commencer et cette méthode est disponible tout au long de mon code.

EDIT:

pour ajouter une méthode à tous les tableaux...

Object[].metaClass.collectMap = collectMap

Si ce que vous avez besoin est d'une simple paire clé-valeur, puis la méthode de la collectEntries devrait suffire.Par exemple

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

Mais si vous voulez une structure semblable à un Multimap, dans lequel il y a plusieurs valeurs par clé, alors vous voulez utiliser l' groupBy méthode

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

Je ne peux pas trouver quelque chose de construit en...mais à l'aide de la ExpandoMetaClass je peux faire ceci:

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

cela ajoute de la collectMap méthode à tous les ArrayLists...Je ne suis pas sûr pourquoi l'ajouter à la Liste ou de la Collection n'a pas fonctionné..Je suppose que c'est une autre question...mais maintenant, je peux le faire...

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

à partir de la Liste pour le calcul de la Carte avec une fermeture...exactement ce que je cherchais.

Edit:la raison pour laquelle je ne pouvais pas ajouter une méthode à la Liste d'interfaces et de la Collecte était parce que je n'ai pas à le faire:

List.metaClass.enableGlobally()

après que l'appel de la méthode, vous pouvez ajouter des méthodes à des interfaces..dans ce cas signifie mon collectMap méthode de travail sur les gammes comme ceci:

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

ce qui donne la carte:[0:0, 1:2, 2:4]

Que penser de quelque chose comme cela?

// 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']
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top