【问题标题】:Groovy map dot keys to nested mapGroovy 映射点键到嵌套映射
【发布时间】:2017-05-27 03:54:02
【问题描述】:

我有一个带有点符号键的地图,但我需要它作为嵌套地图。

[test.key.one: 'value1', text.key.two: 'value2']

现在结果应该是

[
    test: [
        key: [
            one: 'value1',
            two: 'value2'
        ]
    ]
]

这是我对代码的想法

def extract(String key, String value) {

    if(key.contains(".")) {
        def (String target, String subKey) = key.split('\\.', 2)
        return ["$target": extract(subKey, value)]
    } else {
        return ["$key": extractType(value)]
    }

}

但我想知道是否有任何时髦的魔法在闭包中执行此操作,或者在其他好东西的帮助下使其更简单。

【问题讨论】:

    标签: dictionary groovy


    【解决方案1】:

    有一个方便的类:groovy.util.ConfigSlurper

    def map = ['test.key.one': 'value1', 'test.key.two': 'value2']
    def props = new Properties()
    props.putAll(map)
    println new ConfigSlurper().parse(props) // [test:[key:[two:value2, one:value1]]]
    

    唯一的缺点是它需要java.util.Properties 实例,因此您需要从map 创建一个。

    【讨论】:

      【解决方案2】:

      由于 Dany 的回答对我不起作用,我想像 yaml 解析一样支持 Spring Boot,这是我的解决方案:

      Map expandMapKeys(Map source) {
          source.inject([:]) { result, key, value ->
              if (value instanceof Map) value = expandMapKeys(value)
              result + key.tokenize('.').reverse().inject(value) { current, token ->
                  [(token): current]
              }
          }
      }
      
      assert expandMapKeys([a: 'b']) == [a: 'b']
      assert expandMapKeys([a: [b: 'c']]) == [a: [b: 'c']]
      assert expandMapKeys(['a.b': 'c']) == [a: [b: 'c']]
      assert expandMapKeys([a: ['b.c.d': 'e']]) == [a: [b: [c: [d: 'e']]]]
      assert expandMapKeys(['a.b': 'c', 'a.d': 'e']) == [a: [d: 'e']] // not [a: [b: 'c', d: 'e'] !
      

      注意最后一个断言:相同的父映射键将被覆盖。为了解决这个问题,我们需要使用深度合并(我在互联网上找到的)。此外,我们将处理一级列表,因为它们也可以在 yaml 中使用:

      Map expandMapKeys(Map source) {
          source.inject([:]) { result, key, value ->
              if (value instanceof Map) value = expandMapKeys(value)
              if (value instanceof Collection) value = value.collect { it instanceof Map ? expandMapKeys(it) : it }
              merge(result, key.tokenize('.').reverse().inject(value) { current, token ->
                  [(token): current]
              })
          }
      }
      
      Map merge(Map[] sources) {
          if (!sources) return [:]
          if (sources.length == 1) return sources[0]
          sources.inject([:]) { result, map ->
              map.each { key, value ->
                  result[key] = result[key] instanceof Map ? merge(result[key], value) : value
              }
              result
          }
      }
      
      assert expandMapKeys([a: 'b']) == [a: 'b']
      assert expandMapKeys([a: [b: 'c']]) == [a: [b: 'c']]
      assert expandMapKeys(['a.b': 'c']) == [a: [b: 'c']]
      assert expandMapKeys([a: ['b.c.d': 'e']]) == [a: [b: [c: [d: 'e']]]]
      assert expandMapKeys(['a.b': 'c', 'a.d': 'e']) == [a: [b: 'c', d: 'e']]
      assert expandMapKeys([a: ['b.c': 'd'], e: [[f: ['g.h': 'i']], [j: ['k.l': 'm']]]]) == [a: [b: [c: 'd']], e: [[f: [g: [h: 'i']]], [j: [k: [l: 'm']]]]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-06
        • 1970-01-01
        相关资源
        最近更新 更多