I have a list of list that I want to group by marketName and commodityName, by listing price: e.g. ["Terra", "Wheat", 1000.0] - "Terra" is Market name, "Wheat" is Commodity Name, 1000.0 is price
def marketCommodityGroup = [
["Merkato", "Wheat", 1000.0],
["Shola", "Wheat", 1875.0],
["Merkato", "Barley", 5000.0],
["Merkato", "Wheat", 1000.0],
["Merkato", "Wheat", 1500.0]
]
I would like the output to be:
[
["Merkato": ["Wheat" : [1000.0, 1000.0, 1500.0]]],
["Merkato": ["Barley": [5000.0]]],
["Shola": ["Wheat": [1875.0]]]
]
Alright, here's one way of doing it.
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
does exactly what you said, it groups by the market name and commodity namecollect
creates the wanted structure excluding the final k:v
association:
grouping
is the only entry in the key map split so that it can be reordered to desired formprices
is done with the very handy inject
which is Groovy's equivalent for the fold left
operation in functional languagessort
is for flipping the order as you specified - had to quess what the actual logic is so you may want to replace itcollect
does the final map assignment to get the exact wanted formYes, it's a bit dense and magical but you can always move the closures to defs with proper, descriptive names.
[Edit: now returns list of maps, per original question]
Somewhat influenced by Vamsi Krishna's answer, but with 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With