在Groovy中展平嵌套映射

在Groovy中展平嵌套映射,groovy,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] ] 如何使用collect/collectionEntries等进行此操作 或者,如您所见,这些值非常相似。因此,我构建这个嵌套映射结构的方法是,运行一个for

假设我有以下结构:

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]
]
如何使用
collect
/
collectionEntries
等进行此操作


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

您可以创建一个递归函数,该函数将在映射上循环并展平它

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)​
映射嵌套映射=[
“x”:[“a”:2,“b”:3,“z”:4],
“y”:[“a”:20,“b”:30,“c”:40],
“z”:[“a”:200,“b”:300,“c”:400]
]
字符串连接(字符串k、字符串v){
“${k}-${v}”
}
地图(地图地图){
map.collectEntries{k,v->
地图的v实例?
扁平图(v).collectEntries{k1,v1->
键=串联(k,k1)
[(键):v1]
} :
[(k):五]
} 
}
打印地图(嵌套地图)​

< /代码> 关于交替问题(并用@ DaaHaPaTro回音),请考虑以下内容:

给出两个列表:

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


另一种从头开始构建地图的方法是:

def result = ['a'..'c', 'x'..'z']
    .combinations()
    .collect { a, b -> b + '-' + a }
    .indexed()
    .collectEntries { idx, name ->
        [name, ((idx % 3) + 2) * (int)Math.pow(10, idx.intdiv(3))]
    }

您可以使用单指令执行任务:

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] ]
result = nestedMap.inject([:]){ a, k, v ->
  a << v.collectEntries{ [k + '-' + it.key, it.value] }; a }
println result
映射嵌套映射=[
“x”:[“a”:2,“b”:3,“c”:4],
“y”:[“a”:20,“b”:30,“c”:40],
“z”:[“a”:200,“b”:300,“c”:400]]
result=nestedMap.inject([:]){a,k,v->

a我修改了@Paul Walkington的define语法并对其进行了测试:

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

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

看起来像是对原始映射键及其值的简单嵌套迭代;具体问题是什么?不要在[x,y,z]之间循环,而是使用
[x,y,z]
[a,b,c]
创建一个组合,然后调用该函数。类似于
[['x','y','z'],['a','b','c']]]。组合()}
然后调用该函数。小心使用
gstrings
。将“${k}-${k1}”更改为函数调用,以`字符串连接(字符串k,字符串v){“${k}-${v}”`
键未定义。
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] ]
result = nestedMap.inject([:]){ a, k, v ->
  a << v.collectEntries{ [k + '-' + it.key, it.value] }; a }
println result
String concatenate(String k, String v) {
    "${k}-${v}"
}

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