2013-03-26 12 views
10

Groovy Mapsで私の質問。私は、現在のエントリを上書きすることなく、プログラムでGroovyマップに新しいエントリを追加する方法を探してきました。例現在のエントリを上書きせずに複数の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、アクション:レビュー]

しかし、第二のパスを持つ最初のパス上書き: 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マップに値を追加する方法を理解できますか?

答えて

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')) 
2

として、あなたのクラスを定義している関連して表示されるものとキーを使用して異なる値を接続するので、キーを使用して後で検索することができます。あなたの例では、同じキーの値を繰り返し接続しています。一意のキーを選択する必要があります。

マップ内の1つのエントリのためにあなたの値を格納するためにいくつかのクラスを作成します:として(それはあなたが一意にフラグを識別する方法ですので)あなたがキーとしてflagIdを使用するマップを作る

class Stuff { 
    String flagMnemonic 
    String action 
} 

とスタッフ値(検索したいデータなので)。

def editsMap = [:] 

あなたはここで型宣言を使用し、flagIdが文字列の場合、マップのタイプはMap<String, Stuff>になります。

今、あなたはマップにものを置くことができます。また、デフォルト値を設定する?: "default"を使用しての簡単な代替があります

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' 

と外にそれを取り戻す、あなたがwithDefaultを使用することができますあなたの地図を作成するとき:

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

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

4

ます。また、このような何かを行うことができます:

// 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' ] 
9

あなたはGuava's 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] 

This guyはMultimapは、純粋なGroovyのエミュレーションを行います

class GroovyMultimap { 
    Map map = [:] 

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

することができますsyntにはputAtgetAtを使用してください地図操作での砂糖の砂糖。マップオブジェクトでmixinを試すこともできます。

彼はまた、グアバのマルチマップと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") 
} 
+4

次のようにすることもできます: '[:]。withDefault {[]} .with {map-> map.fruit << 'banana'; map.fruit << 'apple'; map.veg << 'ニンジン';マップ} ' –

7

私は別のサイトで同様の質問への答えとして、数年前にこの出くわしました。私はどこから来たのか分からないので、誰かがソースを知っていればここに投稿してください。

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(",") 
} 

を与える:

a -> 1,2,3 

注入multiPut(の使用)方法は魔法を行います。

1

外部クラスなしでマルチマップを行う場合は、代わりにリストのマップを保存するだけで構いません。煩雑ではありません。

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は、常にマルチマップが記述されたのと同じ方法で動作します。マップ内のその項目のリストを常に返します。

関連する問題