在Groovy中合并两个包含列表的地图

时间:2016-07-22 09:35:04

标签: groovy

我正在努力解决以下任务: 里面有两个包含列表的地图:

def m1 = [ k1: [ l1: ['s1', 's2']]]
def m2 = [ k1: [ l1: ['s3', 's4']]]

因此,我希望将单个地图与列表一起添加。

assert merge(m1, m2) == [ k1: [ l1: ['s1', 's2', 's3', 's4']]]

在实践中,地图要大得多,但想法是一样的。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

在groovy控制台中进行了10分钟的试验,结果显示了这段代码:

def m1 = [ k1: [ l1: ['s1', 's2']]]
def m2 = [ k1: [ l1: ['s3', 's4']]]

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

Closure merger
merger = { Map trg, Map m ->
  m.each{ k, v ->
    switch( v ){
      case Map: merger trg[ k ], v; break
      case List: trg[ k ].addAll v; break
    }
  }
}

[ m1, m2 ].each merger.curry( accumulator )

assert [ k1: [ l1: ['s1', 's2', 's3', 's4']]] == accumulator

答案 1 :(得分:1)

以下是我使用Map's collectEntries method投放的内容。我们使用它两次:第一次找到m2中存在的需要合并的子地图。第二次找到需要组合的列表值。

def m1 = [ k1: [ l1: ['s1', 's2']], k2: [l2: ['s5', 's6']]] // include entry not in m2
def m2 = [ k1: [ l1: ['s3', 's4']]]

/* Assumes that the maps contain values that support the + operator */
def combineListMaps = { map1, map2 ->
    map1.collectEntries { key, list -> 
        def list2 = map2[key] ?: []
        [key, list + list2]
    } 
}

m1.collectEntries { key, listMap ->
    def listMap2 = m2[key]
    if (listMap2) 
        [key, combineListMaps(listMap, listMap2)] 
    else
        [key, listMap] 
}