【问题标题】:Groovy - Merge/Group By List of MapsGroovy - 按地图列表合并/分组
【发布时间】:2020-07-01 05:54:59
【问题描述】:

我有一个遵循 List<Map<String,List<String>>> 结构的地图列表

List<Map<String,List<String>>> lstData = []
lstData << ["Year":["FY19"],"Period":["Oct"],"Account":["A1000","A1001"]]
lstData << ["Year":["FY19"],"Period":["Oct"],"Account":["A1001","A1002"]]
lstData << ["Year":["FY19"],"Period":["Nov"],"Account":["A1000","A1001","A1002"]]
lstData << ["Year":["FY19"],"Period":["Dec"],"Account":["A1000","A1002"]]
lstData << ["Year":["FY20"],"Period":["Jan"],"Account":["A1000","A1003"]]

我一直在尝试构建一个可以输出与输入结构相似但合并的列表的东西:

List<Map<String,List<String>>> lstTarget = []
lstTarget << ["Year":["FY19"],"Period":["Oct","Nov"],"Account":["A1000","A1001","A1002"]]
lstTarget << ["Year":["FY19"],"Period":["Dec"],"Account":["A1000","A1002"]]
lstTarget << ["Year":["FY20"],"Period":["Jan"],"Account":["A1000","A1003"]]

请注意 FY19 的 10 月 / 11 月最终如何拥有相同的帐户,因此它们被组合在一起(如果无法完成,这并不重要)

我在这里尝试了几次迭代,但每次我进入兔子洞时,我都会远离“常规”解决方案。以下是我所拥有的:

List lstDims = lstData[0].keySet() as List
List<Map<String,List<String>>> lstOut = []
def result = lstData.groupBy{o -> lstDims.dropRight(1).collect{o."$it"}}.values()
result.each { item ->
    lstOut << item*.keySet().flatten().unique().collectEntries{
        [(it): item*.get(it).findAll().flatten().unique()]
    }
}
println lstOut

// Gets a List Like Below
/*
[
  [Year:[FY19], Period:[Oct], Account:[A1000, A1001, A1002]], 
  [Year:[FY19], Period:[Nov], Account:[A1000, A1001, A1002]], 
  [Year:[FY19], Period:[Dec], Account:[A1000, A1002]], 
  [Year:[FY20], Period:[Jan], Account:[A1000, A1003]]
]
*/

// Repeat to group back by account, ultimately providing the Target List: 

result = lstOut.groupBy{o -> lstDims.takeRight(1).collect{o."$it"}}.values()
lstOut = []
result.each { item ->
    lstOut << item*.keySet().flatten().unique().collectEntries{
        [(it): item*.get(it).findAll().flatten().unique()]
    }
}
println lstOut
assert lstOut == lstTarget

我遇到的两个问题

  1. 感觉不是很“时髦”,但我对 groovy 还是比较陌生,所以我知道什么
  2. 我必须对 groupBy 闭包中的键进行“硬编码”:.groupBy{"${it.Year}${it.Period}"} -- 我想不出一种方法可以将 1 个或多个键传递给分组。

关于上面的#2,我将有一个键列表,以便在执行此代码时进行分组,但是当我不知道如何在.groupBy{sGroupBy} 中使用它时,我正在尝试类似的东西下面

编辑 -- 想出了#2,不确定它是否是最好的方法,但它有效

【问题讨论】:

    标签: groovy hashmap mergemap


    【解决方案1】:

    这是一个相当棘手的问题......

    可以这样做:

    List<Map<String,List<String>>> lstData = []
    lstData << ["Year":["FY19"],"Period":["Oct"],"Account":["A1000","A1001"]]
    lstData << ["Year":["FY19"],"Period":["Oct"],"Account":["A1001","A1002"]]
    lstData << ["Year":["FY19"],"Period":["Nov"],"Account":["A1000","A1001","A1002"]]
    lstData << ["Year":["FY19"],"Period":["Dec"],"Account":["A1000","A1002"]]
    lstData << ["Year":["FY20"],"Period":["Jan"],"Account":["A1000","A1003"]]
    
    lstData.groupBy { it.Year + it.Period }.collect { k, v ->
       v.tail().inject(v.head()) { r, c -> r.Account = (r.Account + c.Account).unique(); r }
    }.groupBy { it.Account }.collect { k, v ->
       v.tail().inject(v.head()) { r, c -> 
           r.Year = (r.Year + c.Year).unique()
           r.Period = (r.Period + c.Period).unique()
           r
       }
    }
    

    不知道是不是比你的好

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 2020-10-26
      相关资源
      最近更新 更多