it-swarm.com.de

Wie füge ich mehrere Groovy-Map-Einträge hinzu, ohne die aktuellen Einträge zu überschreiben?

Meine Frage bei Groovy Maps. Ich habe nach einer Möglichkeit gesucht, programmgesteuert einen neuen Eintrag zu einer Groovy-Map hinzuzufügen, ohne den aktuellen Eintrag zu überschreiben. Zum Beispiel

def editsMap = [:]

lineEdits.flag.each 
{ lineEdits_Flag ->
   editsMap.put('FlagId',lineEdits_Flag.id)
   editsMap.put('FlagMnemonic',lineEdits_Flag.mnemonic)
   editsMap.put('Action',lineEdits_Flag.action)   
   println "editsMap: ${editsMap}"
}

Der erste Durchgang erzeugt diese Karte:
edititsMap: [FlagId: 10001, FlagMnemonic: TRA, Aktion: Überprüfung]

Der zweite Durchgang überschreibt jedoch den ersten Durchgang mit: editsMap: [FlagId: 10002, FlagMnemonic: REB, Action: deny]

Ich versuche, mehrere Einträge in einer Map zu erstellen. Ich brauche meine Karte, um so etwas zu füllen:

editsMap: [FlagId:10001, FlagMnemonic:TRA, Action:review]
editsMap: [FlagId:10002, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:10003, FlagMnemonic:UNB, Action:deny]
editsMap: [FlagId:20001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:20002, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:30001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:40001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:40002, FlagMnemonic:MPR, Action:review]
editsMap: [FlagId:50001, FlagMnemonic:CPT, Action:deny]
editsMap: [FlagId:60001, FlagMnemonic:DTU, Action:deny]
editsMap: [FlagId:70001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:70002, FlagMnemonic:MPR, Action:review]

Sobald ich meine Karte ausgefüllt habe, muss ich in der Lage sein, bestimmte Werte zu finden, um eine Nachricht zu verarbeiten. Ich glaube, dass ich so etwas verwenden kann:

def thisValue = appliedEditsMap[FlagId, '10001'] ?: "default"

eine schnelle Suche zu tun.

Kann mir jemand helfen, zu verstehen, wie man programmgesteuert Werte zu einer Groovy-Map hinzufügt, ohne die bereits in der Map vorhandenen Werte zu überschreiben?

10
kbhuffaker

Du möchtest etwas wie Guavas MultiMap :

Multimap<String, String> myMultimap = ArrayListMultimap.create();

// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");

// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]

Dieser Typ macht eine reine Groovy-Emulation von Multimap:

class GroovyMultimap {
    Map map = [:]

    public boolean put(Object key, Object value) {
        List list = map.get(key, [])
        list.add(value)
        map."$key" = list
    }
}

Sie können putAt und getAt für syntatische Zuckervorgänge in Kartenoperationen verwenden. Sie können auch ein mixin in einem Kartenobjekt versuchen.

Er benutzt auch Groovy mit Guavas Multimap:

List properties = ['value1', 'value2', 'value3']
Multimap multimap = list.inject(LinkedListMultimap.create()) {
    Multimap map, object ->
    properties.each {
        map.put(it, object."$it")
    }
    map
}
properties.each {
    assertEquals (multimap.get(it), list."$it")
}
10
Will

Ich bin darauf vor einigen Jahren als Antwort auf eine ähnliche Frage auf einer anderen Website gestoßen. Ich kann nicht finden, wo es ursprünglich herkam. Wenn jemand die Quelle kennt, posten Sie sie bitte hier.

LinkedHashMap.metaClass.multiPut << { key, value ->
    delegate[key] = delegate[key] ?: []; delegate[key] += value
}

def myMap = [:]

myMap.multiPut("a", "1")
myMap.multiPut("a", "2")
myMap.multiPut("a", "3")

myMap.each {key, list ->
    println "${key} -> $value.list(",")
}

Gibt:

a -> 1,2,3

Die Verwendung der injizierten multiPut () Methode macht die Magie.

9
rifboy

Sie könnten auch so etwas tun:

// Dummy map for testing
lineEdits = [ flag:[
  [id:10001, mnemonic:'TRA', action:'review'],
  [id:10002, mnemonic:'REB', action:'deny'],
  [id:10003, mnemonic:'UNB', action:'deny'],
  [id:20001, mnemonic:'REB', action:'deny'],
  [id:20002, mnemonic:'ICD', action:'review'],
  [id:30001, mnemonic:'REB', action:'deny'],
  [id:40001, mnemonic:'ICD', action:'review'],
  [id:40002, mnemonic:'MPR', action:'review'],
  [id:50001, mnemonic:'CPT', action:'deny'],
  [id:60001, mnemonic:'DTU', action:'deny'],
  [id:70001, mnemonic:'ICD', action:'review'],
  [id:70002, mnemonic:'MPR', action:'review'] ] ]

def editsMap = lineEdits.flag
                        .groupBy { it.id } // Group by id
                        .collectEntries { k, v ->
                          [ k, v[ 0 ] ] // Just grab the first one (flatten)
                        }

assert editsMap[ 60001 ] == [ id:60001, mnemonic:'DTU', action:'deny' ]
5
tim_yates

Wenn Sie die Multimap-Funktion ohne externe Klassen ausführen möchten, können Sie stattdessen nur eine Liste mit Listen speichern. Die Syntax ist nicht umständlich.

def editsMap = [:].withDefault{[]} lineEdits.flag.each { lineEdits_Flag -> editsMap.FlagId << lineEdits_Flag.id editsMap.FlagMnemonic << lineEdits_Flag.mnemonic editsMap.Action << lineEdits_Flag.action println "editsMap: ${editsMap}" } oder wenn Sie Ihre ursprüngliche Syntax wirklich vorgezogen haben, würde dies so aussehen: editsMap.get('FlagId').add(lineEdits_Flag.id) oder sogar dies sollte funktionieren: editsMap.get('FlagId') << lineEdits_Flag.id Der Vorteil dieser Lösung ist, dass es offensichtlicher ist, was Sie tun Konvertiert einzelne Elemente in eine Liste (was nicht der Standard-Kartenvertrag ist), aber es ist immer eine Karte von Listen, die Sie einfach als Karte von Listen verwenden.

Das .get funktioniert immer so wie die Multimap beschrieben wurde - es gibt immer die Liste für dieses Element in der Map zurück.

3
Bill K

Eine Map besteht aus einer Reihe von Zuordnungen von Schlüsselwerten. Sie fügen verschiedene Werte nach Schlüssel ein, damit Sie sie später mit dem Schlüssel finden können. Ihr Beispiel fügt immer wieder Werte für dieselben Schlüssel ein. Sie müssen eindeutige Schlüssel auswählen.

Machen Sie eine Klasse, um Ihre Werte für einen Eintrag in der Karte zu speichern:

class Stuff {
    String flagMnemonic
    String action
}

Erstellen Sie eine Karte, in der Sie flagId als Schlüssel verwenden (weil Sie so die Flagge eindeutig identifizieren) und Stuff als Wert (weil es sich um die Daten handelt, nach denen Sie suchen möchten).

def editsMap = [:] 

Wenn Sie hier Typdeklarationen verwendet haben und flagId ein String ist, lautet der Typ der Map Map<String, Stuff>.

Jetzt können Sie Sachen in die Map einfügen:

lineEdits.flag.each { lineEdits_Flag -> 
    editsMap[lineEdits_Flag.id] = 
    new Stuff(
        flagMnemonic: lineEdits_Flag.mnemonic, 
        action: lineEdits_Flag.action) 
}

und hol es wieder raus mit

def myStuffFor10001 = editsMap['10001']
println myStuffFor10001.flagMnemonic // should equal 'TRA'
println myStuffFor10001.action // should equal 'review'

Es gibt auch eine einfache Alternative zur Verwendung von ?: "default" zum Festlegen von Standardwerten. Sie können withDefault beim Erstellen Ihrer Karte verwenden:

def defaultStuff = new Stuff(
    flagMnemonic: "defaultMnemonic", action:"defaultAction")
def editsMap = [:].withDefault { defaultStuff }

wenn Sie also auf der Karte nach etwas fragen, das dort nicht vorhanden ist, erhalten Sie das angegebene Standardobjekt.

Sie müssen dies in eine Klasse einfügen und diese Klasse dann der Map hinzufügen. Soweit ich Ihre Informationen sehe, ist es sinnvoll, eine Klasse zu speichern, es sei denn, mir fehlt etwas

Sie können Ihre Klasse als definieren

class Flag {

String flagID
String flagMnemonic
String action
}

Now Put your Flag in to your map as

editsMap.put(10000,newFlag(flagID:'10000',flagMnemonic:'TES',action:'tes'))
0

Warum nicht eine Liste und einen Abschluss wie:

editsList = [
[FlagId:10001, FlagMnemonic:TRA, Action:review],
[FlagId:10002, FlagMnemonic:REB, Action:deny],
[FlagId:10003, FlagMnemonic:UNB, Action:deny],
[FlagId:20001, FlagMnemonic:REB, Action:deny],
[FlagId:20002, FlagMnemonic:ICD, Action:review],
[FlagId:30001, FlagMnemonic:REB, Action:deny],
[FlagId:40001, FlagMnemonic:ICD, Action:review], 
[FlagId:40002, FlagMnemonic:MPR, Action:review],
[FlagId:50001, FlagMnemonic:CPT, Action:deny],
[FlagId:60001, FlagMnemonic:DTU, Action:deny],
[FlagId:70001, FlagMnemonic:ICD, Action:review],
[FlagId:70002, FlagMnemonic:MPR, Action:review]
]
def appliedEditsMap = {property,idValue->
     return editsList.find{it[property] == idValue}
}
def thisValue = appliedEditsMap(FlagId, '10001') ?: "default"
0
Dave