将两个映射合并到Groovy中的结果Map

时间:2015-12-17 04:23:29

标签: collections groovy

我有两张地图:

firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85]
secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123]

我需要结果如:

resultMap = [totalProjectCount:101, activeProjectCount:70, completedProjectCount:1, userCount:208]

5 个答案:

答案 0 :(得分:4)

又一个Groovy替代方案:

def firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85, a:1]
def secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123, b:2]

def result = [firstMap, secondMap]*.keySet().flatten().toSet().collectEntries { k ->
    [k, (firstMap[k] ?: 0) + (secondMap[k] ?: 0)]
}

assert result == [a:1, b:2, completedProjectCount:1, userCount:208, activeProjectCount:70, totalProjectCount:101]

如果一个地图中的值在另一个地图中不存在,则此功能也有效(请参阅ab

答案 1 :(得分:3)

要使其成为工具带的可重复使用部分,重要的是提取要合并的功能。

然后合并本身只是创建一个新地图,其中包含地图的所有键,并且通过传递的函数减少了值。

Map mergeWith(Closure fn, Map... maps) {
    maps*.keySet().sum().collectEntries{k->
        [k, maps.findAll{it.containsKey k}*.get(k).inject(fn)]
    }
}

def m1 = [a:53, b:29, c:1, x:85]
def m2 = [a:48, b:41, c:0, y:123]
def m3 = [z:42]

// sum
assert mergeWith({a,b->a+b}, m1, m2, m3)==[a:101, b:70, c:1, x:85, y:123, z:42]
// product
assert mergeWith({a,b->a*b}, m1, m2, m3)==[a:2544, b:1189, c:0, x:85, y:123, z:42]

编辑:根据评论中的要求,进行一些解释

mergeWith采用缩减函数(一个被调用的函数) 两个参数并返回一个值)和一些地图。这意味着,你可以a) 将它用于除了总和之外的其他操作,b)你可以使用它 不止一张地图。

maps*.keySet().sum()是所有键的并集。然后我们 在这组键上collectEntries(构建新地图)。对于价值 找到包含密钥的所有地图(这使得这项工作很顺利 在实际值为false的情况下)并获取k的值 通过传播运营商。然后我们减少(奇怪地命名为inject)列表 传递函数的值。

答案 2 :(得分:2)

Map additionJoin( Map firstMap, Map secondMap )
{
  def resultMap = [:];
  resultMap.putAll( firstMap );
  resultMap.putAll( secondMap );

  resultMap.each { key, value ->
    if( firstMap[key] && secondMap[key] )
    {
      resultMap[key] = firstMap[key] + secondMap[key]
    }
  }

  return resultMap;
}

def firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85]
def secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123]


def resultMap = additionJoin( firstMap , secondMap  )

println resultMap

答案 3 :(得分:1)

试试这个:

Map<String, Integer> resultMap = new HashMap<>(firstMap);       
secondMap.forEach((k, v) -> resultMap.merge(k, v, Integer::sum));

答案 4 :(得分:1)

更有效率,你可以写如下:

Map additionJoin(Map firstMap, Map secondMap)
{
  secondMap.each { key, value ->
    if( firstMap[key])
    {
      firstMap[key] = firstMap[key] + secondMap[key]
    }
  }

  return firstMap;
}
 def firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85]
    def secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123]


    def resultMap additionJoin( firstMap , secondMap  )

     println resultMap

这将是高性能,因为它将使用第三张地图保存。

此外,如果您通过引用了解价值,您也可以像下面这样做:

void additionJoin(Map firstMap, Map secondMap)
{
  secondMap.each { key, value ->
    if( firstMap[key])
    {
      firstMap[key] = firstMap[key] + secondMap[key]
    }
  }
}

def firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85]
def secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123]


 additionJoin( firstMap , secondMap  )

 println firstMap

虽然后来的解决方案妨碍了可读性(有自以为是的观点),可以通过以下附加声明来实现:

  

def resultMap = firstMap

希望它可以帮助你有效地做同样的事情。