Переключение значений на двух многоплановых картах в Groovy - PullRequest
1 голос
/ 30 сентября 2019

Я пишу метод для замены значений на одной из двух карт в зависимости от того, совпадают ли ключи вместе. Например, допустим, у нас есть две карты:

def oldmap = [emails: 1, files:[permissions: 3, config:4]]
def replacementmap = [emails: 2, permissions: 5]

// I want this old map to have updated values for keys that match after the method is called.

replacementPermissions(oldmap, replacementmap)

print oldmap

//prints [emails: 2, files:[permissions: 5, config:4]]

Я написал этот метод, показанный ниже, который работает для одной многоуровневой вложенной карты, но я заметил, что рекурсивное решение будет лучшим вариантом, потому что мое решение не будетРабота с многослойными вложенными картами.

def replacePermissions(read, params){
    read.each{x,y ->
            temp = x
            if (y instanceof Map){
                y.each{x2,y2->
                    temp = x2
                    params.each{xx,yy->
                        if (temp == xx) y.put(x2, yy)
                        if (yy instanceof Map){
                            yy.each{aa, bb->
                                if (temp == aa) y.put(x2, bb)

                            }
                        }
                    }       
                }
            }

            else{
                params.each{x1,y1->
                    if (temp == x1) read.put(x, y1)
                }
            }
        }

    return read
}

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

Прямо сейчас у меня есть это без подписи метода: main.swapsearch () применим для типов аргументов: (java.util.LinkedHashMap, java.lang.Integer) значения: [[lol3: [lol5:4, lol6: 10], lol4: 4], 5] Возможные решения: swapsearch (java.util.Map, java.util.Map)

def swapsearch(Map mapa, Map mapb){
    mapa.each{x,y ->
        temp = x
        mapb.each{x1, y1->
            if (y instanceof Map || y1 instanceof Map){
                swapsearch(y, y1)
            }
            else if (temp == x1){
                mapb.put(x, y1)
            }
        }

    }

    mapb
}


Map oldmap = [lol1: 1, lol2:[lol3: [lol5: 4, lol6: 10], lol4:4]]
Map newmap = [lol1: 5, lol5: 111]

print newmap
newmap = swapsearch(oldmap, newmap)
print newmap

РЕШЕНИЕ с помощью @injecteer: я смогсделать простую рекурсию так:

// Make sure repl map is flattened
def switchMaps( Map src, Map repl ){
  src.each{key,value ->
    if( repl.containsKey(key) ){
      src.put(key, repl[key])

    }
    else if( value && value instanceof Map ){
      replacemaps (value, repl)
    }
  }
  src
}

1 Ответ

1 голос
/ 30 сентября 2019

Некоторая простая рекурсия:

Map oldmap = [emails: 1, files:[permissions: 3, config:4, deep:[ deeper:[ verydeep:1 ] ] ] ] 

Map replacementmap = [emails: 2, permissions: 5, verydeep:400]

def replace( Map src, Map repl ){
  src.each{
    if( repl.containsKey( it.key ) )
      it.value = repl[ it.key ]
    else if( it.value && Map.isAssignableFrom( it.value.getClass() ) )
      replace it.value, repl
  }
}

replace oldmap, replacementmap

assert oldmap.emails == replacementmap.emails
assert oldmap.files.permissions == replacementmap.permissions
assert oldmap.files.deep.deeper.verydeep == replacementmap.verydeep

Если ваш replacementmap также вложен, вы должны предварительно обработать его перед использованием, например:

Map replacementmap = [emails: 2, permissions: 5, deep:[ config:300, toodeep:[ verydeep:400 ] ] ]

Map flatten( Map m, Map res = [:] ) {
  m.each{ k, v ->
    if( !v ) return
    if( Map.isAssignableFrom( v.getClass() ) ) flatten v, res
    else res[ k ] = v
  }
  res
}

Map flatRepl = flatten replacementmap 
assert flatRepl == [emails:2, permissions:5, config:300, verydeep:400]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...