如何使用groovy对列表进行分组

sos*_*oso 4 groovy

我有一个列表,我想按市场名称和商品名称分组,按上市价格:例如["Terra","小麦",1000.0] - "Terra"是市场名称,"小麦"是商品名称,1000.0是价格

def marketCommodityGroup = [
                              ["Merkato", "Wheat", 1000.0],  
                              ["Shola", "Wheat", 1875.0],  
                              ["Merkato", "Barley", 5000.0],  
                              ["Merkato", "Wheat", 1000.0],  
                              ["Merkato", "Wheat", 1500.0] 
                           ] 
Run Code Online (Sandbox Code Playgroud)

我希望输出为:

[
   ["Merkato": ["Wheat" : [1000.0, 1000.0, 1500.0]]],
   ["Merkato": ["Barley": [5000.0]]],
   ["Shola": ["Wheat": [1875.0]]]
]
Run Code Online (Sandbox Code Playgroud)

Esk*_*sko 8

好吧,这是一种做法.

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] ]
}
Run Code Online (Sandbox Code Playgroud)
  • 第一groupBy正是你说的话,它按市场的名称和商品名称
  • collect创建除最终k:v关联之外的有用结构:
    • grouping 是键映射拆分中的唯一条目,以便可以将其重新排序为所需的形式
    • prices完成了非常方便inject的Groovy相当于fold left函数式语言的操作
  • sort 是按照你指定的方式翻转顺序 - 必须要知道实际的逻辑是什么,所以你可能想要替换它
  • 最后collect做最后的地图分配,以获得确切的通缉表格

是的,它有点密集和神奇,但你总是可以用正确的描述性名称将闭包移动到defs.