0

我有两张地图

def configmap = [ "env" :["required": ["team" : "k", "test": "sample"], "optional" : ["anotherkey" : ""]]]
def valuesReplacementMap=[ "env.required.team":"s","env.required.test":"new", "env.optional.anotherkey":"newvalue" ]

valuesReplacementMap具有指向键的路径configmap和需要更新的新值。

我需要将值更新为configmap给出的值valuesReplacementMap

这是我的代码,它有效


def m = [ "env" :["required": ["team" : "k", "test": "sample"], "optional" : ["anotherkey" : ""]]]
def valuesReplacementMap=[ "env.required.team":"s",
           "env.required.test":"new",
           "env.optional.anotherkey":"newvalue" ]

def copyofOrigMap
valuesReplacementMap.each{ key, value->
    copyofOrigMap = m
    key.tokenize(".").inject{ attr, val ->
        if(copyofOrigMap[attr][val] instanceof java.lang.String ){
            copyofOrigMap[attr][val] = value
        }else 
            copyofOrigMap = copyofOrigMap[attr]
        val
    }
}

我的问题是

  1. 有没有办法避免检查instanceof java.lang.String,我这样做是为了看看是否达到叶节点/键
  2. 有没有更简单的方法来实现这整个功能

我经历了一些较早发布的问题,但没有找到任何优化的方法

  1. 在迭代地图时更新地图中的值

  2. Groovy - 更改嵌套映射中字符串的值

  3. 从地图更新 groovy 对象字段

4

1 回答 1

1

解决此问题的一种方法是Eval.me. 以下代码:

def m = [ "env" :["required": ["team" : "k", "test": "sample"], "optional" : ["anotherkey" : ""]]]
def valuesReplacementMap=[ "env.required.team":"s",
                           "env.required.test":"new",
                           "env.optional.anotherkey":"newvalue" ]

valuesReplacementMap.each { k, v -> 
  Eval.me('m', m, "m.${k} = '${v}'")
}

m.each { k, v -> 
  println "$k -> $v"
}

执行时会导致:

─➤ groovy solution.groovy                                          
env -> [required:[team:s, test:new], optional:[anotherkey:newvalue]]
─➤ 

(在 Groovy 版本上:3.0.5 JVM:11.0.8 供应商:Amazon.com Inc. 操作系统:Linux)

其中方法的第一个参数'm'参数Eval.me告诉 eval 我们希望字符串表达式中的值绑定到名称m,第二个参数是值本身。第三个参数是要计算的表达式。

可能有比 eval 更优雅的东西,但这非常简洁,并为您提供了您正在寻找的结果。

还应该注意的是,这仅适用于字符串值,如果任何键或值来自用户输入,则从安全角度来看,使用 Eval 可能是危险的。

具有潜在更好的安全隐患的编辑

作为替代方案,您可以这样做:

def m = [ "env" :["required": ["team" : "k", "test": "sample"], "optional" : ["anotherkey" : ""]]]
def valuesReplacementMap=[ "env.required.team":"s",
                           "env.required.test":"new",
                           "env.optional.anotherkey":"newvalue" ]


valuesReplacementMap.each { k, v -> 
  def tokens = k.tokenize('.')
  def last = tokens.init().inject(m) { a, t -> a[t] }
  last[tokens.last()] = v
}

m.each { k, v -> 
  println "$k -> $v"
}

它产生与Eval.me上面示例相同的输出。

于 2020-09-30T09:24:14.983 回答