Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Groovy中的值组合构建映射列表_Groovy_Combinations - Fatal编程技术网

从Groovy中的值组合构建映射列表

从Groovy中的值组合构建映射列表,groovy,combinations,Groovy,Combinations,我想转换一个包含值列表的HashMap,以生成具有单个值的所有组合 范例 hm = [x : [1,2], y : ['a','b'] ] 预期结果是 res = [ [x: 1, y : 'a'], [x: 1, y : 'b'], [x: 2, y : 'a'], [x: 2, y : 'b'] ] 到目前为止,我提出了这种看法 println hm.values().combinations().collect{[x:it[0],

我想转换一个包含值列表的HashMap,以生成具有单个值的所有组合

范例

hm = [x : [1,2], y : ['a','b'] ]
预期结果是

res = [ [x: 1, y : 'a'],
        [x: 1, y : 'b'],
        [x: 2, y : 'a'], 
        [x: 2, y : 'b']   
]
到目前为止,我提出了这种看法

println hm.values().combinations().collect{[x:it[0],y:it[1]]}

[[x:1, y:a], [x:2, y:a], [x:1, y:b], [x:2, y:b]]
这是可行的,但取决于HashMap中键的名称和数量,因此

hm = [u : [1,2], w : ['a','b'] , z : ['X','Y']]
我必须重写的是

println hm.values().combinations().collect{[u:it[0],w:it[1],z:it[2]]}

所有键名和数字是否都有通用解决方案?

您可以将闭包传递给
.combines()
方法以转换当前组合。然后,您可以使用
[[a,b,c],[1,2,3]]].transpose()
将两个列表中的值“zips”在一起(例如,以下示例中的
[[a,1],[b,2],[c,3]]
),您可以使用
.collectEntries()
将这些对的列表转换为一个映射

考虑以下示例:

defhm=[x:[1,2],y:['a','b']]
def combs=hm.values().组合{args->
[hm.keySet().asList(),args].transpose().collectEntries{[(it[0]):it[1]}
}
梳子{
打印它
}
输出:

[x:1, y:a]
[x:2, y:a]
[x:1, y:b]
[x:2, y:b]
[x:1, y:a, z:X]
[x:2, y:a, z:X]
[x:1, y:b, z:X]
[x:2, y:b, z:X]
[x:1, y:a, z:Y]
[x:2, y:a, z:Y]
[x:1, y:b, z:Y]
[x:2, y:b, z:Y]
现在,我们可以向输入映射添加另一个键,代码将按预期工作:

defhm=[x:[1,2],y:['a','b',z:['x','y']]
def combs=hm.values().组合{args->
[hm.keySet().asList(),args].transpose().collectEntries{[(it[0]):it[1]}
}
梳子{
打印它
}
输出:

[x:1, y:a]
[x:2, y:a]
[x:1, y:b]
[x:2, y:b]
[x:1, y:a, z:X]
[x:2, y:a, z:X]
[x:1, y:b, z:X]
[x:2, y:b, z:X]
[x:1, y:a, z:Y]
[x:2, y:a, z:Y]
[x:1, y:b, z:Y]
[x:2, y:b, z:Y]
使代码更加优雅后的最后一个示例可能如下所示:

defhm=[z:[2,1],y:['a','b',x:['C','b']]
def值=hm.值()
def keys=hm.keySet().toList()
def map=values.compositions{args->
[keys,args].transpose().collectEntries{[(it[0]):it[1]}
}
println图
它打印:

[[z:2, y:a, x:C], [z:1, y:a, x:C], [z:2, y:b, x:C], [z:1, y:b, x:C], [z:2, y:a, x:B], [z:1, y:a, x:B], [z:2, y:b, x:B], [z:1, y:b, x:B]]
值和键的顺序 关于键和值排序的另一个注释。Groovy使用的默认映射实现是
LinkedHashMap
,它保证了条目的顺序(它们被添加的顺序)。这意味着:

  • map.values()
    返回一个
    LinkedHashMap$LinkedValues
  • map.keySet()
    返回一个
    LinkedHashMap$LinkedKeySet

在我们的示例中,我们必须将
keys
变量定义为
hm.keySet()。然后,您可以使用
[[a,b,c],[1,2,3]]].transpose()
将两个列表中的值“zips”在一起(例如,以下示例中的
[[a,1],[b,2],[c,3]]
),您可以使用
.collectEntries()
将这些对的列表转换为一个映射

考虑以下示例:

defhm=[x:[1,2],y:['a','b']]
def combs=hm.values().组合{args->
[hm.keySet().asList(),args].transpose().collectEntries{[(it[0]):it[1]}
}
梳子{
打印它
}
输出:

[x:1, y:a]
[x:2, y:a]
[x:1, y:b]
[x:2, y:b]
[x:1, y:a, z:X]
[x:2, y:a, z:X]
[x:1, y:b, z:X]
[x:2, y:b, z:X]
[x:1, y:a, z:Y]
[x:2, y:a, z:Y]
[x:1, y:b, z:Y]
[x:2, y:b, z:Y]
现在,我们可以向输入映射添加另一个键,代码将按预期工作:

defhm=[x:[1,2],y:['a','b',z:['x','y']]
def combs=hm.values().组合{args->
[hm.keySet().asList(),args].transpose().collectEntries{[(it[0]):it[1]}
}
梳子{
打印它
}
输出:

[x:1, y:a]
[x:2, y:a]
[x:1, y:b]
[x:2, y:b]
[x:1, y:a, z:X]
[x:2, y:a, z:X]
[x:1, y:b, z:X]
[x:2, y:b, z:X]
[x:1, y:a, z:Y]
[x:2, y:a, z:Y]
[x:1, y:b, z:Y]
[x:2, y:b, z:Y]
使代码更加优雅后的最后一个示例可能如下所示:

defhm=[z:[2,1],y:['a','b',x:['C','b']]
def值=hm.值()
def keys=hm.keySet().toList()
def map=values.compositions{args->
[keys,args].transpose().collectEntries{[(it[0]):it[1]}
}
println图
它打印:

[[z:2, y:a, x:C], [z:1, y:a, x:C], [z:2, y:b, x:C], [z:1, y:b, x:C], [z:2, y:a, x:B], [z:1, y:a, x:B], [z:2, y:b, x:B], [z:1, y:b, x:B]]
值和键的顺序 关于键和值排序的另一个注释。Groovy使用的默认映射实现是
LinkedHashMap
,它保证了条目的顺序(它们被添加的顺序)。这意味着:

  • map.values()
    返回一个
    LinkedHashMap$LinkedValues
  • map.keySet()
    返回一个
    LinkedHashMap$LinkedKeySet

在我们的示例中,我们必须将
keys
变量定义为
hm.keySet().toList()
,这仅仅是因为
transpose()
方法需要一个列表。

您可以使用键的组合和值的组合:

def result = []

hm.entrySet().eachCombination { combination ->
    combination.collect{it.value}
    .eachCombination {
        def entry = [:]
        for(int i = 0; i < hm.size(); i++) {
            entry.put(combination[i].key, it[i])
        }
        result << entry
    }

    println result
}

可以使用键的组合和值的组合:

def result = []

hm.entrySet().eachCombination { combination ->
    combination.collect{it.value}
    .eachCombination {
        def entry = [:]
        for(int i = 0; i < hm.size(); i++) {
            entry.put(combination[i].key, it[i])
        }
        result << entry
    }

    println result
}

魔术让我花点时间了解一下,或者看看是否有其他解决方案,我会接受;)很好的解决方案。真的很喜欢你设法让它保持声明性的方式!如何保证
args
中的值顺序与
keySet().asList()中的值顺序匹配?好像它在工作,我只是不知道怎么做,因为
keySet()
是无序的,我认为
values()
也是无序的。你试过不按字母顺序排列的键名吗?@billjamesdev很好<代码>[z:1,a:['a','b']]
工作正常,因此可能*两个列表都是无序的,但顺序相同*(?)@SzymonStepniak让我接受它,还是类似于
SELECT
而不使用
orderby
,可以长期正常工作,但在一些RDBM升级之后,预期的顺序可能会改变?@MarmiteBomber@billjamesdev Groovy使用的默认映射实现是
LinkedHashMap
,因此,条目的顺序定义了值和键的顺序。还值得一提的是,
hm.values()
返回一个
LinkedHashMap$LinkedValues
,而
hm.keySet()
返回一个
LinkedHashMap$LinkedKeySet
。两者都保证顺序(由条目顺序定义)。如果您正在寻找不同的排序,您可能希望将
TreeMap
与自定义比较器一起使用。然而,
LinkedHashMap
中元素的顺序是确定的,因此您不必担心任何随机性或其他问题。神奇!让我花点时间来理解它和/或看看是否有其他解决方案,我很高兴