17

Groovy Maps に関する私の質問です。現在のエントリを上書きせずに、Groovy マップに新しいエントリをプログラムで追加する方法を探していました。例えば

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}"
}

最初のパスで次のマップが生成されます:
editsMap: [FlagId:10001, FlagMnemonic:TRA, Action:review]

しかし、2 番目のパスは、最初のパスを editsMap: [FlagId:10002, FlagMnemonic:REB, Action:deny] で上書きします。

私がやろうとしているのは、1 つのマップ内に複数のエントリを作成することです。次のようなものを設定するには、マップが必要です。

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]

マップにデータを入力したら、メッセージを処理するために特定の値を見つけることができる必要があります。私は次のようなものを使用できると信じています:

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

クイックルックアップを行います。

マップに既にある値を上書きせずに、Groovy マップにプログラムで値を追加する方法を誰かが理解するのを手伝ってくれますか?

4

8 に答える 8

12

Guava の 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]

この男は、Multimap の純粋な Groovy エミュレーションを作成します。

class GroovyMultimap {
    Map map = [:]

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

マップ操作でシンタックス シュガーにputAtandを使用できます。マップ オブジェクトでmixingetAtを試すこともできます。

彼は Guava の multimap で Groovy も使用しています。

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")
}
于 2013-03-26T15:56:35.753 に答える
5

次のようなこともできます。

// 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' ]
于 2013-03-26T15:45:06.340 に答える
3

外部クラスなしでマルチマップを実行したい場合は、代わりにリストのマップを保存するだけで済みます。構文は面倒でも何でもありません。

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}"
}

または、元の構文が本当に好きな場合は、次のようになります: editsMap.get('FlagId').add(lineEdits_Flag.id) または、これでも機能するはずです: editsMap.get('FlagId') << lineEdits_Flag.id このソリューションの利点は、何をしているのかがより明確になる傾向があることです...たとえば、単一のアイテムを変換する魔法のマップではありませんリスト (これは標準のマップ コントラクトではありません) に変換しますが、それは常にリストのマップであり、単にリストのマップとして使用します。

.get は、常に multimap が記述されたのと同じように機能します。つまり、マップ内のそのアイテムのリストを常に返します。

于 2017-06-09T20:52:32.063 に答える
2

マップは一連のキーと値のマッピングです。後でキーを使用してそれらを見つけることができるように、キーごとに異なる値をプラグインします。あなたの例は、同じキーの値を何度も差し込んでいます。一意のキーを選択する必要があります。

マップ内の 1 つのエントリの値を格納するクラスを作成します。

class Stuff {
    String flagMnemonic
    String action
}

flagId をキーとして使用し (これがフラグを一意に識別する方法であるため)、値として Stuff を使用するマップを作成します (それがルックアップするデータであるため)。

def editsMap = [:] 

ここで型宣言を使用し、flagId が String の場合、マップの型は になりますMap<String, Stuff>

これで、マップに物を入れることができます:

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

そしてそれを元に戻します

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

?: "default"また、デフォルト値を設定するために使用する簡単な代替手段がありwithDefault、マップを作成するときに使用できます。

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

そのため、そこに存在しないマップから何かを要求するたびに、指定されたデフォルト オブジェクトが取得されます。

于 2013-03-26T15:20:39.377 に答える
0

これをクラスに入れ、そのクラスをマップに追加する必要があります。私が見るところ、あなたの情報は関連しているので、何かが欠けていない限り、保存するクラスを持つことは理にかなっています

あなたができることは、クラスを次のように定義することです

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'))
于 2013-03-26T15:15:59.363 に答える