Подтвердить что ты не робот

Добавьте две карты в Groovy, суммируя значения для общих ключей

У меня есть две карты в Groovy [a: 1, b: 2] и [b:1, c:3] и хотелось бы создать из них третью карту [a: 1, b: 3, c: 3]. Есть ли команда Groovy, которая делает это?

Изменить. Обратите внимание, что значения на третьей карте являются суммой значений из первых двух карт, если ключи идентичны.

Спасибо

4b9b3361

Ответ 1

Еще одно решение:

def m1 = [ a:1, b:2 ]
def m2 = [ b:1, c:3 ]

def newMap = [m1,m2]*.keySet().flatten().unique().collectEntries {
  [ (it): [m1,m2]*.get( it ).findAll().sum() ]
}

Взяв эпидемический ответ в качестве вдохновения, вы также можете написать метод обработки нескольких карт

def m1 = [a: 1, b: 2]
def m2 = [b: 1, c: 3]

def combine( Map... m ) {
  m.collectMany { it.entrySet() }.inject( [:] ) { result, e ->
    result << [ (e.key):e.value + ( result[ e.key ] ?: 0 ) ]
  }
}

def newMap = combine( m1, m2 )

Ответ 2

Это должно работать для любого количества карт:

def maps = [[a: 1, b: 2], [b:1, c:3]]

def result = [:].withDefault{0}
maps.collectMany{ it.entrySet() }.each{ result[it.key] += it.value }

assert result == [a: 1, b: 3, c: 3]

Выражение maps.collectMany{ it.entrySet() } возвращает список записей карты, например [a=1, b=2, b=1, c=3], а затем каждый из них добавляется к результату.

Другой вариант, если вы хотите сохранить все преобразования в одном выражении и сделать его "более функциональным", это сначала сгруппировать записи по ключу, а затем суммировать значения, но я думаю, что это менее читаемо:

def result = maps.collectMany{ it.entrySet() }
    .groupBy{ it.key }
    .collectEntries{[it.key, it.value.sum{ it.value }]}

Часть groupBy возвращает карту формы [a:[a=1], b:[b=2, b=1], c:[c=3]], а затем преобразует collectEntries, которая отображается в другую, которая имеет одни и те же кеши, но вместо этого имеет сумму списков в значениях.

Ответ 3

В следующем примере показано добавление двух карт на третью карту m3:

Map m1 = [ a:1, b:2 ];
Map m2 = [ b:1, c:3 ];
Map m3 = [:];
m3 << m1
m3 << m2

Ответ 4

Хорошим способом является использование оператора спреда:

def m1 = [ a:1, b:2 ]
def m2 = [ b:1, c:3 ]
def m3 = [ *:m1, *:m2 ]

println "m1 = $m1"
println "m2 = $m2"
println "m3 = $m3"

* Кредит: http://mrhaki.blogspot.ch/2009/09/groovy-goodness-spread-operator.html

Вышеприведенный код не работает в groovysh, но он отлично работает в консоли groovy. (для версии 1.8)

Ответ 5

Я не думаю, что для этого есть готовый метод, возможно, используйте что-то вроде:

def m1 = [a: 1, b: 2]
def m2 = [b: 1, c: 3]
def newMap = (m1.keySet() + m2.keySet()).inject([:]) { 
    acc, k -> acc[k] = (m1[k] ?: 0) + (m2[k] ?: 0); acc 
}

Ответ 6

Это делает:

Map additionJoin( Map map1, Map map2 )
{
  def result = [:];
  result.putAll( map1 );
  result.putAll( map2 );

  result.each { key, value ->
    if( map1[key] && map2[key] )
    {
      result[key] = map1[key] + map2[key]
    }
  }

  return result;
}

def a = [a: 1, b: 2]
def b = [b:1,c:3]

def c = additionJoin( a, b )

println c

Ответ 7

def merge(map1, map2) { 
    def add = { map, entry -> map << entry }
    map2.inject(map1.inject([:], add), add)
}