Есть ли в Groovy встроенный способ обхода / преобразования структуры данных? - PullRequest
0 голосов
/ 05 июня 2019

Имея вложенную структуру данных карты / списка / скаляра в Groovy, есть ли у нее какой-нибудь довольно "Groovy" способ пройтись по ней и создать преобразованную структуру?

Самый чистый способ, который я написал до сих пор, не так уж и плох, рекурсивный ходок, который применяет замыкание. Но я бы приветствовал совет, если есть встроенный способ, которого мне не хватает.

Например, возьмите эту структуру данных и замените все экземпляры ${VARIABLE} на REPLACED через String s внутри:

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 голосов
/ 05 июня 2019

Вот лучшее из того, что я придумал до сих пор:

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
  }
}

Это зависит от умного Groovyswitch заявление.Он не расширяемый, вы не можете просто подключить свои собственные обработчики типов, но это так просто, что вам не нужно.По умолчанию он выполняет гибридное копирование, создавая новые экземпляры List s и Map s, но сохраняя ссылки на исходные скалярные или несопоставленные типы.Это может быть сделано для глубокого копирования, в соответствии со следующими примерами преобразования идентичности:

// 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
  }
}))

Мысли?Лучшие способы?

...