4

市場名と商品名、リスト価格でグループ化したいリストのリストがあります。

def marketCommodityGroup = [
                              ["Merkato", "Wheat", 1000.0],  
                              ["Shola", "Wheat", 1875.0],  
                              ["Merkato", "Barley", 5000.0],  
                              ["Merkato", "Wheat", 1000.0],  
                              ["Merkato", "Wheat", 1500.0] 
                           ] 

出力を次のようにしたいと思います。

[
   ["Merkato": ["Wheat" : [1000.0, 1000.0, 1500.0]]],
   ["Merkato": ["Barley": [5000.0]]],
   ["Shola": ["Wheat": [1875.0]]]
]
4

5 に答える 5

8

さて、ここにそれを行う1つの方法があります。

def mapped = marketCommodityGroup.groupBy {
  [(it[0]) : it[1]]
}.collect { k,v ->
  def grouping = k.find { true }
  def prices = v.inject([]) { acc,val -> acc + val[2] }
  [ (grouping.key) , [ (grouping.value) : prices ] ]
}.sort { left, right ->
  right[0] <=> left[0]
}.collect {
  [(it[0]) : it[1] ]
}
  • 最初にあなたgroupByが言ったことを正確に実行します。市場名と商品名でグループ化します
  • collectk:v最終的な関連付け を除いて、必要な構造を作成します。
    • groupingキーマップ分割の唯一のエントリであるため、目的の形式に並べ替えることができます
    • prices関数型言語でinjectの操作に相当するGroovyの非常に便利な方法で行われますfold left
  • sort指定した順序を反転するためのものです-実際のロジックが何であるかを質問する必要があったため、それを置き換えることができます
  • lastcollectは最終的なマップ割り当てを行い、正確に必要なフォームを取得します

はい、それは少し密度が高く魔法のようですが、適切でわかりやすい名前の定義にクロージャーをいつでも移動できます。

于 2013-10-12T09:48:23.710 に答える
3

楽しみのためだけに別のバージョン;-)

def marketCommodityGroup = [ [ "Terra", "Wheat", 1000.0  ],  
                             [ "Shola", "Wheat", 1875.0  ],  
                             [ "Terra", "Barley", 5000.0 ],  
                             [ "Terra", "Wheat", 1000.0  ],  
                             [ "Terra", "Wheat", 1500.0  ] ] 

def group( tree, data ) {
    if( data.size() > 2 ) { group( tree."${data.head()}", data.tail() ) }
    else {
        if( !tree."${data.head()}" ) tree."${data.head()}" = []
        tree."${data.head()}" << data[ -1 ]
    }
}

def grouped = { [:].withDefault{ owner.call() } }()
marketCommodityGroup.each {
    group( grouped, it )
}

assert grouped == ['Terra':['Wheat':[1000.0, 1000.0, 1500.0], 'Barley':[5000.0]],
                   'Shola':['Wheat':[1875.0]]]
于 2013-10-14T12:07:55.400 に答える
3

[編集: 元の質問ごとにマップのリストを返すようになりました]

Vamsi Krishna's answer に多少影響を受けましたが、 chained withDefault:

def marketCommodityGroup = [
                              ["Terra", "Wheat", 1000.0],  
                              ["Shola", "Wheat", 1875.0],  
                              ["Terra", "Barley", 5000.0],  
                              ["Terra", "Wheat", 1000.0],  
                              ["Terra", "Wheat", 1500.0] 
                           ]

def marketCommodityMap = [:].withDefault{ [:].withDefault{ [:].withDefault {[]} } }

// map looks like
// ["Terra-Wheat": ["Terra": ["Wheat": [1000.0 ...], "Barley": [5000.0] ]]]
// but we will discard the outer compound key                            
marketCommodityGroup.each { market, commodity, price ->    
    marketCommodityMap["${market}-${commodity}"][market][commodity] << price
}

def listOfMaps = marketCommodityMap.values()
println listOfMaps
于 2013-10-12T18:21:13.197 に答える
1

これは役立つかもしれません:

def marketCommodityGroup = [["Terra", "Wheat", 1000.0],  
                            ["Shola", "Wheat", 1875.0],  
                            ["Terra", "Barely", 5000.0],  
                            ["Terra", "Wheat", 1000.0],  
                            ["Terra", "Wheat", 1500.0]]


def marketMap = [:].withDefault{[:]}  
def commodityMap = [:].withDefault {[]}

marketCommodityGroup.each{ market, comm, price ->
  commodityMap[comm].add(price)
}
println("commodityMap: "+commodityMap)                            

marketCommodityGroup.each{ market, comm, price ->
  marketMap[market][comm] = commodityMap[comm]
}                            
println("MarketMap: "+marketMap)

出力:

commodityMap: [Wheat:[1000.0, 1875.0, 1000.0, 1500.0], Barely:[5000.0]]
MarketMap: [Terra:[Wheat:[1000.0, 1875.0, 1000.0, 1500.0], Barely:[5000.0]], Shola:[Wheat:[1000.0, 1875.0, 1000.0, 1500.0]]]
于 2013-10-12T09:32:45.330 に答える
1
def expected = [
   ["Terra": ["Wheat" : [1000.0, 1000.0, 1500.0]]],
   ["Terra": ["Barley": [5000.0]]],
   ["Shola": ["Wheat": [1875.0]]]
]                         

assert expected == marketCommodityGroup
                       .groupBy([{it[0]}, {it[1]}]) //Grouping based on 2 keys
                       .collectEntries{key, val-> 
                            [key, val.collectEntries{k, v -> //Collect entries
                                [k, v.collect{it[2]}.sort()]}] //Sorted price
}.inject([]){list, key, val -> //To transform result as a list
    val.each{k, v -> list << [(key): [(k): v]]}
    list
}

データのマップ表現のみが必要で、注入を使用しない場合は、次のようになります。

[
 'Terra':['Wheat':[1000.0, 1000.0, 1500.0], 'Barley':[5000.0]], 
 'Shola':['Wheat':[1875.0]]
]
于 2013-10-12T20:18:44.413 に答える