groovy是否有内置的方法来遍历/转换数据结构?

时间:2019-06-05 02:15:32

标签: list dictionary data-structures groovy traversal

给定Groovy中的嵌套地图/列表/标量数据结构,它是否有任何漂亮的“ Groovy”方式来遍历它并生成转换后的结构?

到目前为止,我编写的最干净的方法还不错,这是一个使用闭包的递归walker。但是,如果有一种我想念的内置方式,我欢迎提出建议。

例如,采用此数据结构,并在其中的${VARIABLE} s中将REPLACED的所有实例替换为String

def config = [
  '${VARIABLE}: 'scalar',
  'foo': [
    'bar': 1,
    'baz': ['a', 'b', 'c', 'd'],
    'my_${VARIABLE}_key': null
  ],
  'bak': 1,
  'ban': 'abcd',
  'boo': [
    ['x': 1, 'y': 2, 'subst': '${VARIABLE}'],
    ['a': 1, 'b': 2]
  ]
]

1 个答案:

答案 0 :(得分:0)

这是到目前为止我想出的最好的方法:

def walk(v, Closure transform ) {
  switch (v) {
    case null:
      return null
    case Map:
      return v.collectEntries { mk, mv -> [ transform(mk), walk(mv, transform) ] }
    case List:
      return v.collect { lv -> walk(lv, transform) }
    default:
      return transform(v)
  }
}
给出上述示例数据的

可能会这样应用:

def engine = new groovy.text.SimpleTemplateEngine()

def subs = ['VARIABLE': 'REPLACED']

def newconfig = walk(config) { v ->
  switch (v) {
      case String:
        return engine.createTemplate(v).make(subs)
      default:
        return v
  }
}

这依赖于Groovy的智能switch语句。它不是可扩展的,您不能只是插入自己的类型处理程序,但是它是如此简单,您不需要。默认情况下,它会进行混合复制,创建ListMap的新实例,但保留对原始标量或不匹配类型的引用。也可以按照以下身份转换示例进行深复制:

// Identity transform, shallow copy scalars
assert (config == (walk(config) { v -> v.clone() }))

// Identity transform, deep copy scalars where possible
assert (config == (walk(config) {
  v ->
  try {
    return v.clone()
  } catch (java.lang.CloneNotSupportedException ex) {
    return v
  }
}))

有什么想法吗?更好的方法?