在 Groovy 中展平嵌套映射

Mat*_*oob 4 groovy

假设我有以下结构:

Map<String,Map<String,Integer>> nestedMap = [
"x": ["a": 2, "b": 3, "c": 4],
"y": ["a": 20, "b": 30, "c": 40],
"z": ["a": 200, "b": 300, "c": 400]
]
Run Code Online (Sandbox Code Playgroud)

我想压平这个结构并得到:

[
"x-a" : 2, 
"x-b" : 3, 
"x-c" : 4,
"y-a" : 20, 
"y-b" : 30, 
"y-c" : 40,
"z-a" : 200, 
"z-b" : 300, 
"z-c" : 400
]
Run Code Online (Sandbox Code Playgroud)

我怎样才能用collect/collectEnteries等来做到这一点?

或者,如您所见,这些值非常相似。所以我构建这个嵌套地图结构的方式是运行一个 for 循环迭代[x,y,z]并将我的地图的条目设置为等于一个迭代[a,b,c]并返回地图的函数。有没有办法跳过这个嵌套结构并在功能上将元素附加到大地图中?

Pau*_*ton 6

您可以创建一个递归函数,该函数将遍历地图并将其展平。

Map<String,Map<String,Integer>> nestedMap = [
"x": ["a": 2, "b": 3, "z": 4],
"y": ["a": 20, "b": 30, "c": 40],
"z": ["a": 200, "b": 300, "c": 400]
]

String concatenate(String k, String v) {
"${k}-${v}"
}

def flattenMap(Map map) {    
    map.collectEntries { k, v -> 
       v instanceof Map ? 
          flattenMap(v).collectEntries {  k1, v1 -> 
             key = concatenate(k,k1)
            [ (key): v1 ]  
         } :
            [ (k): v ]  
     } 
}


print flattenMap(nestedMap)?
Run Code Online (Sandbox Code Playgroud)


Mic*_*ter 2

关于替代问题(并回应@damahapatro 的评论),请考虑以下内容。

给定两个列表:

def list1 = ['x', 'y', 'z']
def list2 = ['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

f和一个给出适当值的函数,然后我们可以使用inject(它将在迭代组合时累积一个映射(例如[x,a]):

def m = [list1, list2].combinations().inject([:]) { map, combo ->
    assert combo.size() == 2
    def a = combo[0]
    def b = combo[1]
    map["${a}-${b}" as String] = f(a,b)
    map
}

assert m == [
"x-a" : 2, "x-b" : 3, "x-c" : 4,
"y-a" : 20, "y-b" : 30, "y-c" : 40,
"z-a" : 200, "z-b" : 300, "z-c" : 400
]
Run Code Online (Sandbox Code Playgroud)